Typically, the user interface in a client application or Rich Internet Application (RIA) contains controls that display application domain data and allows users to modify and submit changes to the data. Defining application logic to control this process in the control's code-behind makes them complex and difficult to understand, maintain, evolve, test, and re-use.
Any of the following conditions justifies using the solution described in this pattern:
- You want to maximize the code that can be tested with automation. (The user interface is hard to test automatically.)
- You want to share code between pieces of the user interface (UI) that require the same underlying behavior.
- You want to separate presentation and business logic from UI logic to make the code easier to understand and maintain.
- You want to allow a user interface designer to easily create or modify the UI for your application; by doing this, developers can focus on the application's logic and structure.
- The data that you want to display requires some form of conversion or adaptation before it can be displayed in the user interface.
- The data that you want to display requires some form of validation before it can be updated by the user interface.
Separate the responsibilities for the visual display of the user interface and the presentation state and behavior into different classes named, respectively, the view and the presentation model. The view class manages the user interface controls and encapsulates any visual state or behavior that is specific to the UI. The presentation model class encapsulates presentation behavior and state and acts as a façade onto the underlying model. The view acts as an observer of the Presentation Model, and the Presentation Model acts as an observer of the Model. Figure 1 provides a logical view of the Presentation Model pattern.
Presentation Model pattern logical view
The presentation model should be designed to provide a public interface that can be easily consumed by a view, thereby reducing or eliminating the need for any complex code within the view for it to be able to interact cleanly with the presentation model. Specifically, the presentation model should be designed to support data binding, commands, and data templates.
By correctly designing the presentation model, developers can leverage the powerful data-binding capabilities provided by Windows Presentation Foundation (WPF) and Silverlight. With data binding, controls that are bound to application data automatically reflect changes when the underlying data changes its value. Similarly, data binding can automatically update the underlying data when the user modifies it in the user interface, such as if the user edits the value in a TextBox element, the underlying data value is automatically updated to reflect that change. In WPF and Silverlight, any dependency property of a control can be bound to a property on the presentation model.
To support data binding, the presentation model should implement the INotifyPropertyChanged interface. Similarly, any objects provided to the view through properties should support the INotifyPropertyChanged or INotifyCollectionChanged interfaces. Implementing these interfaces allows the data binding mechanism to monitor the presentation model for changes so that it can automatically update the UI. The presentation model is typically set as the data context for the view so that the binding expressions defined in the view resolve to the corresponding properties on the presentation model.
Commands in WPF and Silverlight represent actions that the user can perform through the user interface, such as the user submitting the current order by clicking the Submit button or menu item. Commands separate the visual representation of an available action with the actual code that implements that action.
Commands allow the user interface to interact with the application's functionality in a declarative and automatic way without requiring any complex event handling code in the view's code-behind file. Interaction between the UI and the command is two-way. The command can be invoked as the user interacts with the UI, and the UI can be automatically updated as the underlying command becomes enabled or disabled.
WPF controls can be easily associated with a command through the Command property. The control will automatically invoke the target command when the user interacts with that control. Silverlight controls can use the Click.Command attached behavior that the Composite Application Library provides to achieve the same behavior for any control that derives from ButtonBase. Other control events can easily be supported by creating a suitable attached behavior for it. For more information, see "Extending Command Support" in the Commands technical concept.
The presentation model should encapsulate the implementation logic for commands so that it can be unit tested and more easily maintained. The presentation model should make commands available to the view by exposing them as ICommand valued properties. The Composite Application Library provides the DelegateCommand and CompositeCommand classes to make this easy to do. For more information, see the Commands technical concept.
For more information about commands in WPF, see Commanding Overview on MSDN.
By using data templates, a visual designer can easily define how an object will be rendered in the user interface. A data template declares user interface controls that will be data bound at run time to the underlying object. The designer can dramatically modify or change the visual representation of an object without changing the underlying object.
In WPF, you can specify the data template for an object type at the application level—WPF automatically applies the data template for any objects of that type that are displayed in the UI. In Silverlight, you have to explicitly specify the data template for an object within the control that is to display it.
When you implement the Presentation Model pattern in a WPF or Silverlight application, you can define its view as a data template. Data templates are flexible and lightweight. UI designer can use them to easily define the visual representation of a presentation model without requiring any complex code. Data templates are ideally suited for views that do not require any UI logic (code-behind).
For more information about data templates, see Data Templating Overview.
A variant of the Presentation Model pattern named Model-View-ViewModel is commonly used in WPF and Silverlight applications. For more information, see WPF Apps With The Model-View-ViewModel Design Pattern in MSDN magazine.
To see an example implementation of the Presentation Model pattern, see the files WatchListPresentationModel.cs, WatchListView.xaml, and WatchListService.cs in the Stock Trader Reference Implementation (these files are located in the WatchList folder of the StockTraderRI.Modules.Watch project).
The Presentation Model pattern has the following liabilities:
- There are more solution elements to manage.
- You need a way to synchronize the view with the presentation model. Typically, this is done through data binding.
- The model is not aware of the presentation model. Therefore, if the model is changed by any component other than the presentation model, the presentation model must be notified. Typically, notification is implemented with the Observer pattern. For more information about the Observer pattern, see Exploring the Observer Design Pattern.
The following patterns are related to the Separated Presentation pattern:
- Supervising Presenter. This pattern is similar to the Presentation Model pattern and is suitable for situations in which the view can be directly bound to the model. The presenter coordinates the interaction between the view and the model by interpreting user gestures into actions against the model and changes in the model into user interface actions.
For more information about the Presentation Model pattern, see the following:
- Presentation Model on Martin Fowler's Web site
For more information about software design patterns applied in the Composite Application Library and Stock Trader Reference Implementation, see Patterns in the Composite Application Library.