Using the Presentation Model Pattern with WPF Views and CAB/CAL (PRISM)

The Established MVP Pattern
When creating WPF views for an application based on Microsoft Patterns & Practices Composite UI Application Block (CAB), a UI framework for developing applications in Windows Forms that also supports hosting WPF Views, the pattern we adopted for binding controls was to call methods from the OnViewReady method to retrieve or create the bound objects in the presenter and pipe them into the view's code behind via method calls on the views interface.  These methods in the view then set the DataContext of the target control, or indeed of the view itself, to the passed in object.  In some cases, when binding directly to an ItemsControl, the passed in object was a collection, and this was bound to the ItemsSource of the target control.  Here is an example:

Presenter:

public override void OnViewReady()

      {

          base.OnViewReady();

          BindView();

      }

      public void BindView()

      {

          ...

          View.BindCustomers(_customers);

          ...

      }

 

View Code Behind:

public void BindCustomers(ObservableCollection<CustomerBindingObject> customers)

{

    customerslistBox.ItemsSource = customers;

}

The Presentation Model
The Presentation Model is an architectural pattern introduced by Martin Fowler and is the basis of Microsoft’s more specialized MVVM (Model-View-ViewModel) pattern.  It is the favoured approach of the Composite Application Library (CAL or PRISM), the UI framework for developing applications in WPF and Silverlight,  and is employed for separating the responsibilities for the visual display of the user interface and the presentation state and behaviour.  This approach is not so different from the traditional MVP pattern, except in the way it handles data binding.

As before, methods are called from the OnViewReady method to retrieve or create the bound objects in the presenter.  But rather than piping them into the view's code behind for subsequent binding to controls in the view, the bound objects are stored in properties on the presenter.  The presenter itself, or presentation model as it should be called, is then bound directly to the data context of the view.

Now, in the Composite Application Library (CAL or PRISM), the way they implement this, seems a backward step to me.  After storing the binding objects in properties on the Presentation Model, they call a method on the view (as we did in the established MVP pattern above), and pass "this" (the instance of the presentation model) in.  They then set the DataContext of the view to the passed in presentation model, in the called method.


I felt that this unnecessarily cluttered the views code behind and so came up with what I feel is a cleaner approach.  I have created an interface called IBindableView.  This interface implements just one property shown below:

IBindableView Interface:

public interface IBindableView

{

    object DataContext { get; set; }

}

 By inheriting from this interface, the interface for a WPF view will expose the DataContext of that view.  For example:

ICustomersView Interface:

public interface ICustomersView : IBindableView

{

}

 This then allows you to directly set the DataContext from the OnViewReady method in the presenter, without needing to call methods on the view:

CustomersPresentationModel:

public override void OnViewReady()

{

    base.OnViewReady();

    ...

    View.DataContext = this;

    ...

}

You can then bind your controls directly to the properties on your presentation model in XAML.  You can also expose your commands as properties on the presentation model and bind to these directly in XAML.  I shall explain how to do this in another post on Delegate Commands.

November 24 2009
blog comments powered by Disqus