The PresentationModel Pattern

I’ve mentioned the PresentationModel pattern a couple times on this blog and figured I better discuss it in a bit more detail. I discovered the presentation model pattern almost two years ago when I had the opportunity to attend the WPF Bootcamp at Microsoft. PresentationModel is very similar to Model-View-ViewModel and a distant relative of MVC/MVP. The idea behind PM is to remove any code behind and decouple the logic that determines the GUI behavior from the logic that communicates with data services (db access, web services etc.). The PM pattern is enabled by WPF/Silverlight’s binding model which easily allows for properties on an object to synchronize with controls on a form.

There are three pieces to the presentation model.

1) View – The view is the GUI definition (xaml) and related code behind.

2) Model – An object representation of the data to be displayed to the user. Note, this is not the data model as retrieved from the database or web service. It is a PresentationModel (hence the name of the pattern) as will be displayed to the user in the GUI.

3) Presenter – Coordinates services that modify/access data, propogating that data to the model and linking the model to the view.

View

Ideally the view has only 1 property exposed via an interface to set the DataContext. The DataContext is what bound controls will look to in order to obtain their display values. The controls will update the DataContext when their values have changed which will ultimately update the model and allow the presenter to know what data has changed, and thus needs to be updated to the db or web service.

Sample View

public partial class MyView : IMyView
{
    public MyView()
    {
        InitializeComponent();
    }

    public object Context
    {
        set { DataContext = value; }
    }
}

Notice this is a partial class, the other half of the partial class being the control definitions as defined by the xaml.

Model

The model is simply a data object that contains properties that hold the data to be displayed to the user. This can be strings/ints/doubles that are displayed in TextBoxes or TextBlocks as well as List data (any IEnumerable really, I just tend to prefer Lists) for ListBoxes/ListViews/Combos. This model’s properties will be bound to controls. The presenter will be responsible for linking this object to the DataContext of the view.

One area of confusion I should try and clear up relates to the Model. The Model is what differentiates this pattern from others. The Model does not necessarily refer to the data model as retrieved from the database. It is a model of the data as displayed in the GUI towards the user. It is not uncommon to roll multiple data models (ie data models from the db or web services) into one single PresentationModel. The presentation model is really one layer of abstraction from the database to what the user will see. This allows a developer/designer to hide the database and make a more intuitive and appealing application that is more digestible to the end user.

Sample Model

public class MyModel : IMyModel
{
    public int SomeIntValue { get; set; }

    public string SomeStringValue { get; set; }

    public List SomeListOfStrings { get; set; }
}

Presenter

The presenter is the center to all of this. It coordinates the view and model in addition to services that maintain data via the db or web services.

Sample Presenter

public class MyPresenter : IMyPresenter
{
    private readonly IMyView view;
    private readonly IMyModel model;
    private readonly IMyService service;

    public MyPresenter(IMyView view, IMyModel model, IMyService service)
    {
        this.view = view;
        this.model = model;
        this.service = service;

        Initialize();
    }

    private void Initialize()
    {
        view.Context = model;
    }

    public void Load()
    {
        DataModel dataModel = service.GetData();
        // Here we need to map the data model to our presentation
        // model, AutoMapper is newish project that maps objects
        // based on convention.  We can also manually map
        // properties on one object to another.
        model.SomeIntValue = dataModel.SomeInt;
        model.SomeStringValue = dataModel.SomeString;
    }
}

Below is quick example of how the model is bound to controls in the xaml.

<TextBlock Text="{Binding SomeIntValue}" />
<TextBox Text="{Binding SomeStringValue}" />
<ListBox ItemsSource="{Binding SomeListOfStrings}" />

So what are the advantages of this pattern. One is flexibility in terms of refactoring given the use of interfaces. But most importantly is the ability to unit test the GUI. Combine the above pattern with using an ICommand implentation and you can programmatically test button clicks and every aspect of an application. Use a mocking framework like Moq and everything can be tested with ease.

Two quick things to mention. You might be asking why I’m using interfaces all over the place. I’m trying to use interface based design aka coding by contract. This is to make refactoring easier in the future, both refactoring of the classes themselves in addition to simplifieing unit testing both in development and refactoring. It also supports using an IoC container. As long as all of the contracts are registered in the container with their corresponding implementations resolving the presenter, in addition to other objects, is a simple task.
Second, I should mention I did not implement INotifyPropertyChanged on the PresentationModel which would be a must givin the way the presenter is coordinating the view and model. But I’ll save that for another post. I’ll also include how to reference properties in a strongly typed way using Linq rather than using strings when firing off the NotifyPropertyChanged event.

Advertisements

One thought on “The PresentationModel Pattern

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s