Displaying a second view on btnShowView2.Clicked
is some kind of business logic, so the right place for implementing this is in the event handler of presenter1
which deals with that event (I assume that presenter1 is registered to all relevant button-click events of View1
). Lets call it HandleBtnView2Click
, so the initial code inside that handler might look like this:
void HandleBtnView2Clicked(object sender, EventArgs e))
{
IView2 view2 = new View2();
Model2 model2 = model1.GetRefToModel2(); // or whatever is needed to get model2
View2Presenter presenter2 =new View2Presenter(view2,model2);
presenter2.show();
}
But actually, this is not a good solution, since it would imply the presenter2 layer must be linked against the UI library (in your case WinForms), which in worst case prevents automatic testing.
The better solution is to delegate the creation of View2
to a third instance, which can be easily mocked out. In general, its possible to use an abstract factory for this. In the specific case, it is also possible to use View1
for the creation of View2
. Add a method to your IView1
interface:
interface IView1
{
// ...
IView2 CreateView2();
}
and use it in the code above:
void HandleBtnView2Clicked(object sender, EventArgs e))
{
IView2 view2 = view1.CreateView2(); // view1 is of type IView1 and a member of presenter1
Model2 model2 = model1.GetRefToModel2(); // or whatever is needed to get model2
View2Presenter presenter2 =new View2Presenter(view2,model2);
presenter2.show();
}
Now when you want to automatically test your presenter1
, provide it with a mock implementation of view1 which implements the CreateView2
method in a manner returning a mock of view2. In the View1
class, you implement CreateView2()
to return the new View2()
, so the responsibility for creating views stays at the the view layer.
You can go a step further if you want and make presenter1
testable in isolation from presenter2
. If you think that is necessary, create an interface IPresenter2
and put the whole creation code above into an abstract "presenter factory":
void HandleBtnView2Clicked(object sender, EventArgs e))
{
IPresenter presenter2 = presenterFactory.CreatePresenter2(model1);
presenter2.show();
}
The presenterFactory
has to be injected into your presenter1 at construction time and can be replaced by a mock in your test suite. If that's necessary, you have to decide for yourself. It will add an additional layer of complexity to your code for the benefit of better testability.