1

I have a WinForm with modular/dockable subforms (WeifenLuo). What is best practice to pass events/information between the forms?

For example: I want a "SelectionChanged" event in SubForm1 change what is highlighted in SubForm2. Problem is, there might be zero SubForm2-Tabs, one or multiple instances.

Currently, if a new instance of a SubForm is requested by the user, a function like this is called:

    private void toolStripMenuItemSubForm1_Click(object sender, EventArgs e)
    {
        SubForm1 subForm1 = new SubForm1();
        subForm1.Show(dockPanelMain, DockState.Document);
    }

The MainForm has no record of all subforms except dockPanelMain.Contents.

Edit: I know how forms can interact with each other and how events per se work. My problem is that a event from SubForm1 can alter different other SubForms, but they might not exist at a given point in time, or there might be multiple instances and I dont want to chain it through the MainForm for every single event.

thetemplar
  • 97
  • 2
  • 3
  • 9
  • Possible duplicate of [Communicate between two windows forms in C#](http://stackoverflow.com/questions/1665533/communicate-between-two-windows-forms-in-c-sharp) – René Vogt May 09 '16 at 12:38
  • Add an event and rise it. Someone (another form) may subscribe/unsubscribe to it and do something. – Sinatr May 09 '16 at 12:41
  • 1
    THis is really too broad... but here are my two cents, what about a global event hub? If you have a global hub when you create a form which has to receive an event subscribe it, and then the form which must fire the event calls the hub to rise it. Clean and simple. – Gusman May 09 '16 at 12:44
  • A global event hub was my first idea, but it seemed a bit complicated and bloated at first, but so far my only sollution. – thetemplar May 09 '16 at 12:47
  • @RenéVogt I thought it was too at the beginning, but this question is different, it's not a parent<=>children relationship but children<=>children where the childrens does not knows one another – Irwene May 09 '16 at 13:11

2 Answers2

3

IMHO, you're taking this the wrong way around

A teacher used to present me this kind of problems this way : "A CEO does not necessarily know everybody who works for him. However, every worker will know it's CEO" (pardon the phrasing, it's (hastily) translated)

This could be applied to your problem as well :

Pass the parent instance to the childrens that will have the responsibility to hold into this instance and subsribe to the events that they should be listening to.

This way, your parent class will only have to take care of raising the events, the childrens will do the work of updating themselves

EDIT:

To work between the dockpanel's content classes it's basically the same thing.

Pass the Contents property of the dockpanel to the child classes. Since it's a collection (and thus a reference type), the child classes will always have access to the latest 'version' of the collection.

You'll just have to get all the instances that are of interest for you by filtering this collection

Filtering example (I may have missed a cast at the end) :

IEnumerable<SubForm2> sf2 = dockContents.Where(sf => sf is SubForm2)
Irwene
  • 2,807
  • 23
  • 48
  • I see it more as a problem like: How can one worker interact with others (0-n) without the CEO as middleman. – thetemplar May 09 '16 at 12:43
  • I like the concept. No need of extra classes or distributors. Added a foreach-existing-content loop and a `dockPanelMain.Contents.ContentAdded` event to my constructor. Should work fine, maybe a bit bloated later. – thetemplar May 09 '16 at 13:05
  • @thetemplar This is only possible because all of these instances belong to a common herarchy. If they did not, your only solution would have been Gusman's one AFAIK – Irwene May 09 '16 at 13:09
0

I suggest passing an Event class that contains an event / delegate into your Subform constructor. Each subform can subscribe to events that are raised at the appropriate time.

auburg
  • 1,373
  • 2
  • 12
  • 22