Yesterday I was reading CAB message boards and came across number of threads with questions about implementing MVP patter in CAB. Indeed, among provided samples only the walk-through uses MVP but its rather simplistic. Luckily some of these questions got answered.
First of all I've learned of the Smart Client Baseline Architecture Toolkit project, that aims to provide collection of guidance for implementing Smart Clients (including Hands-On-Labs, How-Tos and Reference Applications). Although the project just started there are already first deliverables (and they promise to release frequently on weekly base). What's important, the provided reference application show MVP in more complex scenario. It also confirms my feelings that there was something wrong in my implementation.
If you want to learn about MVP pattern itself, see The Humble Dialog Box paper, that was mentioned as one that best describes the style of MVP that Smart Client team is doing. Another great paper is Twisting The Triad: The evolution of the Dolphin Smalltalk MVP application framework. It starts with widget-based approach, then introduces MVC and finally explains MVP and shows how it simplifies design while leveraging strengths of both earlier patterns. You can also read the MVP paper from Martin Fowler (although I read it a year ago and till now I didn't had a clue how to implement it properly).
Here is how I understand Model-View-Presenter pattern right now (you can refer to the diagram from last post):
The Model
This is the data upon interface will operate. It is typically a domain object and there is intention that such objects should have no direct knowledge of user interface. Instead the Observer pattern (in other words events) is used to communicate changes in model to the view.
The View
This is the presentation part that is responsible to display the contents of a model. The model is expected to trigger change notifications whenever its data is modified and these allow the view to reflect these changes on screen. This allows multiple views to be connected to a single model.
The view is also responsible for handling all raw user interface events generated by user gestures. These events are then translated into operations meaningful for given view and in most cases routed to the presenter.
The Presenter
This component governs how the model can be manipulated and changed by the user interface. Most of the user interface logic is built into a presenter class. The main difference between presenters and controllers is that presenter is directly linked to its associated view. That means the view can pass user interface events to presenter but also presenter can directly affect the state of the view.
How does it all fit in CAB? First of all you should remember that the WorkItem is NOT the model. State in WorkItam can be used to store model objects, but WorkItem is a higher level concept used to group components working together to fulfill some use case.
As far as I know there is no base class for Presenter. But in summary for Controller class you can read that it is “A base class for controllers and presenters that provides access to the WorkItem and State“. So the only thing that is missing is reference to owning View and we can create Presenter by extending this class. I also decided to declare it with generic parameters of ViewType and WorkItemType to avoid much repetitive code.
public class Presenter : Controller where WorkItemType : WorkItem{
private ViewType _view; public ViewType View
{
get { return _view; }
set { _view = value; }
}
public new WorkItemType WorkItem
{
get { return base.WorkItem as WorkItemType; }
}
}
Then I use following code to instantiate the presenter when the view is created:
private MyPresenter _presenter;
[
CreateNew]public MyPresenter Presenter{
get { return _presenter; } set {
_presenter =
value; _presenter.View =
this; }
}