views:

168

answers:

3

I am attempting to use MVP in WinForms and am confused on how to best handle coordination among child views.

For example, I have a parent view that has two child views. Events on one child view need to cause an action to be taken by the second child view.

Should the parent view control this directly? It seems like I am bypassing the MVP pattern by doing this.

Or should the child views take each other as constructor parameters? In that case, when an event was fired by the first child view, the 2nd child view would receive the event and then notify its presenter that something has occurred? The presenter then needs to get the data from the first child view (which it doesn't even know about) in order to tell the 2nd child view what to do. It seems convoluted so I feel like I am missing something.

Here is some pseudo-code for the situation:

public class ParentView : UserControl, IParentView
{
    private ChildViewOne childViewOne;
    private ChildViewTwo childViewTwo;
    private ParentViewPresenter presenter;

    private RegisterEvents()
    {
        childViewOne.EventOccured += new EventHandler(HandleEvent);
    }

    private void HandleEvent()
    {
        childViewTwo.DoSomething();
    }
}
A: 

Taking other child views in constructor seems like a bad idea. What will you do if another child view needs to be added in future?

It would be better if you route your child event through the parent view. How are you violating the MVP if you route your events through the parent view?

Raminder
Do you mean like I am doing currently or if the ParentView exposed the union of all the events of its children and just passed the events through to its presenter?
jameswelle
A: 

You could look at the Event Aggregator pattern. It will allow you to keep everything loosely coupled. Prism comes with one and it's easy enough to use without having to buy into the whole Prism framework/library.

Your code could then look like this:

public class ChildViewOne {
    private IEventAggregator evtAggregator;

    public ChildViewOne(IEventAggregator evtAggregator) {
        this.evtAggregator = evtAggregator;
    }

    private void OnEventOccured(){
        evtAggregator.GetEvent<EventOccured>().Publish();
    }
}

publish class ChildViewTwo {
    private IEventAggregator evtAggregator;

    public ChildViewTwo(IEventAggregator evtAggregator) {
     evtAggregator.GetEvent<EventOccured>().Subscribe(OnEventOccured);
    }

    private void OnEventOccured() {
        // Do something here...
    }
}

EDIT: Brian Noyes has ported the prism event aggregator to winforms. Check it out here, on his blog

Joepro
A: 

I would create a property of the IChildView interface called SiblingView (or something more appropriate given the business context of your app). You don't even have to add it as a param in the constructor, but have the Interface include a method called SetSiblingView(). You could call it from the constructor. You could then have an event OnSiblingEventFired().

It seems less convoluted to me, but maybe thats just because thats generally how I have approached this type of issue in the past.

But I agree, without knowing too much detail having the parent control it doesn't seem to be following the MVC pattern.

tb