Choosing a design pattern for the user interface of your application involves weighing trade-offs between testability, complexity, developer tool support, and capabilities. There are two very prominent camps in user interface patterns: Forms & Controls and Model-View-Something (Controller, Presenter, ViewModel, etc.). Martin Fowlers’ article GUI Architectures (http://www.martinfowler.com/eaaDev/uiArchs.html ) provides a detailed history and comparison of some of these approaches.
Many applications use Forms & Controls pattern for their user interface. This is partially because it is the default pattern Visual Studio uses to create an application and more likely because it is a very simple pattern with a low barrier of entry for developers. Though Forms & Controls approach may be simpler to implement for small applications which can get away with limited or no unit testing, larger and more complex applications are increasingly difficult to maintain using this approach. This inherent lack of testability of a Forms & Controls pattern make is a poor choice for implementing larger applications.
To solve this problem of testability, software architects have turned to more advanced user interface patterns such as Model-View-Controller, Model-View-Presenter (a.k.a. Supervising Controller and Passive View), Presentation Model, and other variants of these patterns. The goal of these patterns is creating user interface classes which can be easily tested, and minimizing the amount of code which resides in the view (a notoriously difficult part of the application to test in an automated fashion). Though these patterns are technology independent, the underlying GUI framework lends itself to certain patterns. Windows Forms technology meshed particularly well with the Model-View-Presenter pattern, while implementing a Presentation Model pattern in Windows Forms required masses of synchronization code. Windows Presentation Foundation, on the other hand, fits very well with the Presentation Model because of its advanced data binding technology which eliminates the need to write masses of synchronization code between the view and presentation model.
Each screen is implemented as a View and Presentation Model pair. Each class has distinct responsibilities. The view is responsible for how data is presented on the screen, and the presentation model is responsible for what gets presented on the screen and the actions which can be performed on that data.
The view consists of both the XAML and the code-behind, and displays the data it gets from the presentation model. Most views will be implemented mostly in XAML with a little supporting C#. Layout and user interaction are the primary responsibilities of the view. The view interprets user actions and forwards them to the presentation model as commands.
Commands are used to invoke behavior. The command pattern decouples the presentation model from the actual input event which invoked some functionality. Commands capture the intent of the user, not necessarily the actual mechanics of how they indicated that intent. For example, the presentation model doesn’t need to know if the user clicked the save button, pressed CTRL+S, or selected save from a menu option. All the presentation model needs to concern itself with is that the data should be saved. The command object also provides a good mechanism for the presentation model to indicate if an action is enabled through the CanExecute callback of the command.
While the PresentationModel receives communication from the View via Commands, if it needs to notify the View of something, it should use events. Events allow us to define the means of communication on the presentation model itself. While some events should be built into the presentation model base class (notifying when properties changed), others are screen specific and should be in the screen’s presentation model. There is no separate interface implemented by the View as in MVP. Having the presentation model provide events simplifies unit test code, because you don’t need to create dummy views.
We’ll cover more in part 2.