Events on the Main form, User Control - Communication

San24
San24 used Ask the Experts™
on
Experts,

Whats the best way to communicate between events on the Main form and events on a User Control.

Let me explain -

I have a set of Tabs in a Tab Control. Each Tab is a separate file and consists of a User Control. The User Control itself contains a Sub Tab Control and has other User Controls with events within its Tab pages. Lets say a simple Button click on each User Control within a Tab page, when the user clicks on the Button, I need to check if there is filename associated with the Main Tab. If it does not have a file name, I need to show a Save File Dialog. And give the Tab a file name. I want the Save Dialog only if there is no Filename for the Tab opened.

Now, the Main form has Menu Items with [Save, Save As..etc] When I click on Save As the Save File Dialog needs to open. And the Tab gets a new file name.

Now lets say, the user Saves the file first thrrough the Save As menu item and then Clicks the Button on the User Control, then there is no Save File Dialog cause there is already a Filename associated with the tab.

How do I get access to the filename from both the Menu Item event and the User Control event, so that I can keep track to show the Save File Dialog.

What is the best approach, keeping in mind I need to do other events like Open, Save file while closing events etc. I

Thanks!



Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®

Author

Commented:
Bubbling of Events? Is that the way to go?
you might use events, yes, or define delegates and then use them as callbacks
High School Computer Science, Computer Applications, Digital Design, and Mathematics Teacher
Top Expert 2009
Commented:
Each UserControl should track whether it has a filename associated or not as that is the most logical place...only it knows its own "state".

You've boiled it down in your question:

    "How do I get access to the filename from both the Menu Item event and the User Control event, so that I can keep track to show the Save File Dialog."

There isn't ONE best answer because you really have two different kinds of communication:
(1) From the UserControl to the Main UI.
(2) From the Main UI to the UserControl.

For #1, "bubbling up" of events makes the most sense.  Raise a custom event that broadcasts the "sender" (source UserControl).  The event is bubbled up thru the UserControl and then out to the main UI where it can be handled.

For #2, you first have to determine which is the active UserControl and then tell it to do something.  You can even tell it to start the process in #1 which would indirectly cause the Main UI to do something (when the event is received).
Exploring SQL Server 2016: Fundamentals

Learn the fundamentals of Microsoft SQL Server, a relational database management system that stores and retrieves data when requested by other software applications.

Author

Commented:
Alexey,

Thats just bubbling of events right? oris it something different .. Callback? Can you give me a simple example.

Author

Commented:
Idle Mind,

Exactly - since there are two kinds of communication needed, I was wondering what would be the best way to approach this. So I have to implement two way communication right?

If I had used MDI Parent forms, I didn`t have to do all this.

Let me play with your solution and I`ll let you know how it works out.
Mike TomlinsonHigh School Computer Science, Computer Applications, Digital Design, and Mathematics Teacher
Top Expert 2009

Commented:
"If I had used MDI Parent forms, I didn`t have to do all this."

I disagree, both points still apply to Mdi apps as well.

You have to communicate "in" from the MdiParent to the children.
You have to communicate "out" from the MdiChildren to the MdiParent form.

Author

Commented:
Interesting. I haven`t used MDI Forms, but read that the parent keeps track of its open and active children. I so I was guessing the communication wa done internally. I should have known before I spoke, sorry about that.
Mike TomlinsonHigh School Computer Science, Computer Applications, Digital Design, and Mathematics Teacher
Top Expert 2009

Commented:
It does keep track of the open MdiChildren in a collection and also gives you the ability to grab the current active MdiChild but it doesn't help any further than that since it doesn't know what you want to do with those children...  ;)

The children are still custom forms with their own sets of controls on them.  It's up to you to decide how they communicate with each other.

Author

Commented:
Bubbling of Event  - What am I missing here? Is this the right way to do it?

I`m getting an Error  "An object reference is needed for non static field, method or property"

 //User Control File - SubUserCntrl
 public event EventHandler MyCusEvent;

        public SubUserCntrl()
        {
            InitializeComponent();
            Dock = DockStyle.Fill;      
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (MyCusEvent != null)
                MyCusEvent(this, e);        
        }
           
//InitializeComponent() of Form1

SubUserCntrl.MyCusEvent += new System.EventHandler(MyCusEvent);

//Form1.cs
//Everytime I click the button1 on SubUserCntrl - Is the function below called?
 private void MyCusEvent(object sender, EventArgs e)
        {
         //Do Something here
            MessageBox.Show("Test");
        }
Mike TomlinsonHigh School Computer Science, Computer Applications, Digital Design, and Mathematics Teacher
Top Expert 2009

Commented:
It works for me:

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            subUserCntrl1.MyCusEvent += new EventHandler(subUserCntrl1_MyCusEvent);
        }

        void subUserCntrl1_MyCusEvent(object sender, EventArgs e)
        {
            MessageBox.Show("Test");
        }
    }

    public partial class SubUserCntrl : UserControl
    {
        public event EventHandler MyCusEvent;

        public SubUserCntrl()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (MyCusEvent != null)
                MyCusEvent(this, e);        
        }
    }

Author

Commented:
Idle Mind,

Do I have to create a new instance of the User Control

 subUserCntrl subUserCntrl1 = new subUserCntrl();

    public partial class Form1 : Form
    {
     
        // ????
        subUserCntrl subUserCntrl1 = new subUserCntrl();

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            subUserCntrl1.MyCusEvent += new EventHandler(subUserCntrl1_MyCusEvent);
        }

        void subUserCntrl1_MyCusEvent(object sender, EventArgs e)
        {
            MessageBox.Show("Test");
        }
    }

    public partial class SubUserCntrl : UserControl
    {
        public event EventHandler MyCusEvent;

        public SubUserCntrl()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (MyCusEvent != null)
                MyCusEvent(this, e);        
        }
    }
Mike TomlinsonHigh School Computer Science, Computer Applications, Digital Design, and Mathematics Teacher
Top Expert 2009

Commented:
I dropped on from my ToolBox onto my form...

But it would work the same with a dynamic control.  Just give it a location and add it to the controls collection:

        subUserCntrl subUserCntrl1 = new subUserCntrl();

        private void Form1_Load(object sender, EventArgs e)
        {
            subUserCntrl1.Location = new Point(25, 25);
            this.Controls.Add(subUserCntrl1);
            subUserCntrl1.MyCusEvent += new EventHandler(subUserCntrl1_MyCusEvent);
        }

Author

Commented:
Not related to the topic...What is a better programming practice .. To put the initialization statements in Form1() or Form1_Load(object sender, EventArgs e)
Mike TomlinsonHigh School Computer Science, Computer Applications, Digital Design, and Mathematics Teacher
Top Expert 2009

Commented:
Depends on what your initializing...  ;)

In the constructor your form doesn't have a handle yet so you can't base things off of the size of anything...the Load() event would be necessary then.

Other than that it doesn't matter too much for most things.

Author

Commented:
Okay I`m a bit confused now.

I already have an instance of the User Control loaded like this .. dynamically.  
My first tep is to load all the User Controls through MenuItems events. So would I just add it to the Controls collection in this step?


 private void NewFileSitch(ToolStripItemClickedEventArgs e)
        {

            switch(e.ClickedItem.ToString())
            {
                case "ParamOne":

                    TabsUserCntrl TUC_H = new TabsUserCntrl();
                    subUserCntrl HX = new subUserCntrl();
                    HX.Name = "XYZ";
                    TabPage TP_H = new TabPage();
                    TP_H.Text = "Param One";
                    TP_H.BackColor = Color.White;

                    TabCount();

                    TUC_H.panel1.Controls.Add(HX);  
                    //TUC_H.WindTab.Controls.Add(HX);
                    TP_H.Controls.Add(TUC_H);
                    MainTabCntrl.TabPages.Add(TP_H);  

                    break;

                case "ParamTwo":
                    TabsUserCntrl TUC_C = new TabsUserCntrl();
                    abcUserCntrl CX = new abcUserCntrl();
                    TabPage TP_C = new TabPage();
                    TP_C.Text = "Param Two";
                    TP_C.BackColor = Color.White;

                    TabCount();

                    TUC_C.panel1.Controls.Add(CX);    
                    TP_C.Controls.Add(TUC_C);
                    MainTabCntrl.TabPages.Add(TP_C);  
                    break;

                default:
                    break;
            }
        }
Mike TomlinsonHigh School Computer Science, Computer Applications, Digital Design, and Mathematics Teacher
Top Expert 2009

Commented:
It looks like it's being added properly.  =)

Where are you wiring up the event then?  You need to wire up the event for that actual instance that you created...

Author

Commented:
So I`m creating an instance here -

case "ParamOne":

                    TabsUserCntrl TUC_H = new TabsUserCntrl();
                    subUserCntrl HX = new subUserCntrl();
                    HX.Name = "XYZ";
                    TabPage TP_H = new TabPage();
                    TP_H.Text = "Param One";
                    TP_H.BackColor = Color.White;

                    TabCount();

Would I be wiring the event here?

something like this?

case "ParamOne":

                    TabsUserCntrl TUC_H = new TabsUserCntrl();
                    subUserCntrl HX = new subUserCntrl();
                    HX.Name = "XYZ";
                    TabPage TP_H = new TabPage();
                    TP_H.Text = "Param One";
                    TP_H.BackColor = Color.White;
                    //Added this
                    HX.MyCusEvent += new EventHandler(HX_MyCusEvent);

                    TabCount();


and then do this -

private void HX_MyCusEvent(object sender, EventArgs e)
        {
         //Do Something here
            MessageBox.Show("Test");  
        }


I`m I getting this completely wrong? Can you give me an example?
Mike TomlinsonHigh School Computer Science, Computer Applications, Digital Design, and Mathematics Teacher
Top Expert 2009

Commented:
Yes...that should be right...but I'm guessing you're going to say that it doesn't work?  =\

If so, I think I'd either need to see more code or possibly play with a test project to figure out where the problem is...

Author

Commented:
Haha...actually it works fine! I just need to understand the process - a semi newbie here. Right now I`m just doing trial and error - not the most efficient way. Let me play with this more and then close this thread. Thanks for your patience and help.

Now, I`ve figured out bubbling events from the User Control to the Main UI. Now I need to work on reversing it. I`ll keep you updated.

Isn`t Bubbling nothing but Publishing and Subscribing events? Or is that completely different.
Mike TomlinsonHigh School Computer Science, Computer Applications, Digital Design, and Mathematics Teacher
Top Expert 2009

Commented:
Yes...bubbling is just subscribing to raised events.  The actual "bubbling", though, occurs when the event is raised from a control that is nested more than one level deep and it has to be captured and then rebroadcast at an intermediate level before it reaches the main level.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial