Where and how to reference composite MVP components?
- by Lea Hayes
I am learning about the MVP (Model-View-Presenter) Passive View flavour of MVC. I intend to expose events from view interfaces rather than using the observer pattern to remove explicit coupling with presenter.
Context: Windows Forms / Client-Side JavaScript.
I am led to believe that the MVP (or indeed MVC in general) pattern can be applied at various levels of a user interface ranging from the main "Window" to an embedded "Text Field". For instance, the model to the text field is probably just a string whereas the model to the "Window" contains application specific view state (like a persons name which resides within the contained text field).
Given a more complex scenario:
Documentation viewer which contains:
TOC navigation pane
Document view
Search pane
Since each of these 4 user interface items are complex and can be reused elsewhere it makes sense to design these using MVP.
Given that each of these user interface items comprises of 3 components; which component should be nested? where? who instantiates them?
Idea #1 - Embed View inside View from Parent View
public class DocumentationViewer : Form, IDocumentationViewerView {
    public DocumentationViewer() {
        ...
        // Unclear as to how model and presenter are injected...
        TocPane = new TocPaneView();
    }
    protected ITocPaneView TocPane { get; private set; }
}
Idea #2 - Embed Presenter inside View from Parent View
public class DocumentationViewer : Form, IDocumentationViewerView {
    public DocumentationViewer() {
        ...
        // This doesn't seem like view logic...
        var tocPaneModel = new TocPaneModel();
        var tocPaneView = new TocPaneView();
        TocPane = new TocPanePresenter(tocPaneModel, tocPaneView);
    }
    protected TocPanePresenter TocPane { get; private set; }
}
Idea #3 - Embed View inside View from Parent Presenter
public class DocumentationViewer : Form, IDocumentationViewerView {
    ...
    // Part of IDocumentationViewerView:
    public ITocPaneView TocPane { get; set; }
}
public class DocumentationViewerPresenter {
    public DocumentationViewerPresenter(DocumentationViewerModel model, IDocumentationViewerView view) {
        ...
        var tocPaneView = new TocPaneView();
        var tocPaneModel = new TocPaneModel(model.Toc);
        var tocPanePresenter = new TocPanePresenter(tocPaneModel, tocPaneView);
        view.TocPane = tocPaneView;
    }
}
Some better idea...