How the Presentation Model could look like when using Silverlight 2.0

In this post I will give you an example how the Presentation Model pattern could be implemented when using Silverlight 2.0. I will not dig deep into the Presentation Model, so if you don’t hear of it or want to read more about it, you can visit this page.

A short description of the Presentation Model follows here:

Represent the state and behavior of the presentation independently of the GUI controls used in the interface

To make the code examples in this post short, I have only used one property in my original domain entity, and the entity used in the post is Name. It only has one property called Name, to make it easy to identify objects in the example, I have added some suffix, which I don’t use in my real applications. So the Name entity has the name NameEntity. The NameEntity from the domain model (or can be a DataContract) look likes this:

public class NameEntity
{
   public string Name { get; set; }
}


I decided to use the Repository pattern on the Client side, so the Repository responsible for the NameEntity has the name NameRepository. On the client-side the Repository can for example make a call to a WCF service on the server side. When I use the Repository Pattern, I make sure all my Repositories implements an interface, the reason to this is to follow the Dependency Inversion Principle, it will also make it easier for me to write unit test. Here is the code for the NameRepository:

public interface INameRepository
{
   NameEntity GetName();

   void SaveName(NameEntity name);
}


public class NameRepository : INameRepository
{
    public NameEntity GetName()
    {
       //Make a WCF call all use ADO.Net Data Services etc.
       return new NameEntity() { Name = "John Doe" };
    }


    public void SaveName(NameEntity name)
    {
       //Make a call to a WCF service or use ADO.Net Data Services etc.
    }
}


Note: I haven’t implemented the call to a WCF Service, or the use of ADO.Net Data Services in this example.


When using the Presentation Model pattern, we will create a class which should represents a model for presentation purpose. The following code is the Presentation Model for the NameEntity:

public class NamePresentationModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private INameRepository _nameRepository;
    private NameEntity _nameEntity;


    public NamePresentationModel(INameRepository nameRepository)
    {
        if (nameRepository == null)
           throw new ArgumentNullException("nameRepository");

        _nameRepository = nameRepository;
    }


    public string Name
    {
       get
       {
           CheckIfNameEntityIsLoaded();

           return _nameEntity.Name;
       }
       set
       {
           if (string.IsNullOrEmpty(value))
              throw new ArgumentException("Name can't be set to null or an empty string!");

           CheckIfNameEntityIsLoaded();

           _nameEntity.Name = value;

           RaisePropertyChanged("Name");
       }
   }


   public void Load()
   {
      _nameEntity = _nameRepository.GetName();
   }


   public void Save()
   {
      _nameRepository.SaveName(_nameEntity);
   }

       
   private void CheckIfNameEntityIsLoaded()
   {
      if (_nameEntity == null)
         throw new ArgumentException("You must first call the Load method of the NamePresentationModel!");
   }

       
   protected void RaisePropertyChanged(string propertyName)
   {
       var propertyChanged = this.PropertyChanged;

       if (propertyChanged != null)
          propertyChanged(this, new PropertyChangedEventArgs(propertyName));
   }
}


The decided to implement the INotifyPropertyChanged interface if we are going to bind the Presentation Model’s Name property to several UIElement. I decided to make sure I could pass the type INameRepository as an parameter to the Presentation Model’s constructor. I want the Presentation Model to handle the actions and also to make sure I don’t add to much code or dependency to the Code behind file. As you can see in the code, I NEVER pass my NameEntity to the User Interface, instead the Presentation Model is the new model to be use on a User Interface level (bind to UIElements etc). Here is the Code behind of the XAML page:

public partial class Page : UserControl
{
   private NamePresentationModel _namePresentationModel;

   public Page()
   {
      InitializeComponent();

      _namePresentationModel = new NamePresentationModel(new NameRepository());

      this.Loaded += Page_Loaded;
   }


   void Page_Loaded(object sender, RoutedEventArgs e)
   {
       LoadFromPresentationModel();
   }


   private void Button_Click(object sender, RoutedEventArgs e)
   {
      _namePresentationModel.Save();
   }


   private void LoadFromPresentationModel()
   {
      _namePresentationModel.Load();
      myTextBox.Text = _namePresentationModel.Name;
   }


   private void SyncWithPresentationModel()
   {
       _namePresentationModel.Name = myTextBox.Text;
   }
}


As you can see the code in the code behind page is relative clean. In this code example I have manually populate the User Interface with information, but we can also use data binding (more about that later in this post).

In the Page constructor I instantiate the Presentation Model to be used for the current View, I also inject an instance of the NameRepository object to the NamePresentaitonModel’s constructor. I could have hidden the dependency of the NameRepository in the NamePresentationModel, but that will violate the Dependency Inversion Principle, and if I want to write a Unit test for my NamePresentationModel, I can now simply inject a fake object of the NameRepository. One good idea here could be the use of the Factory pattern to create the Presentation Model, by doing so we could make sure the Page don’t even need to know about the Repository passed to the Presentation Model. I could also make sure that the default constructor of the Presentation Model instantiate the Repository, by doing it I would have the possibility to inject a Repository, or remove the instantiation of the Repository within the code behind.

public NamePresentationModel()
{
    _nameRepository = new NameRepository();
}

 

public Page()
{
   InitializeComponent();

   _namePresentationModel = new NamePresentationModel(new NameRepository());

   this.Loaded += Page_Loaded;
}


I made a call to the PresentationModel’s Load method within the Page_Loaded event handler. I don’t want the Code-behind to be responsible for the use of the Repositories, so I gave the Presentation Model the responsibility instead. The NamePresentationModel class, will more or less remind us of the Active Record pattern. If you look at the code behind, you can see that the Button_Click will make a call to the Presentation Model’s Save method. The reason why the Save method is added to the Presentation Model, is to simulate the Save button’s “event” when writing a Unit test for example.

The code behind will have the responsibility to map the Presentation Model to the User Interface. Here is the XAML used in this example:

<UserControl x:Class="ICommandExample.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="400" Height="300">
    <Grid x:Name="LayoutRoot" Background="White">
        <StackPanel VerticalAlignment="Center">
            <TextBox Margin="10" x:Name="myTextBox"></TextBox>
            <Button Margin="10" Content="Save" Click="Button_Click"></Button>
        </StackPanel>
    </Grid>
</UserControl>

Instead of letting the code behind map the Presentation Model to the UIElements, we can use the Binding expression and also take advantage of User Input validation (you can read about User Input Validation in Silverlight 2.0 in my previous post). Here is the XAML code where DataBinding is used and the code is followed by the new code behind code:

<UserControl x:Class="ICommandExample.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="400" Height="300">
    <Grid x:Name="LayoutRoot" Background="White">
        <StackPanel x:Name="myStackPanel" VerticalAlignment="Center">
            <TextBox Margin="10" x:Name="myTextBox" Text="{Binding Name, Mode=TwoWay}"></TextBox>
            <Button Margin="10" Content="Save" Click="Button_Click"></Button>
        </StackPanel>
    </Grid>
</UserControl>

public
partial class Page : UserControl { private NamePresentationModel _namePresentationModel; public Page() { InitializeComponent(); _namePresentationModel = new NamePresentationModel(new NameRepository()); this.Loaded += Page_Loaded; } void Page_Loaded(object sender, RoutedEventArgs e) { LoadFromPresentationModel(); } private void Button_Click(object sender, RoutedEventArgs e) { _namePresentationModel.Save(); } private void LoadFromPresentationModel() { _namePresentationModel.Load(); myStackPanel.DataContext = _namePresentationModel; } }


Because the Mode of the Binding expression is set to TwoWay, we don’t need to get the value of the TextBox when we hit the save button, because it will be automatically set to the new value of the TextBox.

12 Comments

  • Nice example

    I have used the combination RepositoryPattern in the PresentationModel to hide webservices in a project I superviced, but it got to confusing for my coworkers.

    But I would have thrown in a Presenter to manage the repositoryhandling away from the presentation model.

  • Great Article. If you dont mind, I had a few questions.
    1) How does Model-View-ViewModel (MVVM) and PresentationModel differ and if the difference isn't that much, which one would you choose?
    2)Also if you are using ADO.NET Data-Services (you would be using LINQ along with it) and how would you go about with writing tests for it? Would you use NInject (Dependency Injection) on the INameRepository Interface?

    Thanks,
    K.


  • @Kanual:
    1) Interesting question, well Microsoft have the talent to take a well known pattern, and add a new name for it ;) Model-View-ViewModel is more for WPF applications and focused on Data Binding and using the ICommand interface and bind commands to the Command property of a UI element. But for me it's a rip of the Presentation Model. So I will never say that I use the Model-View-ViewModel, I will use the well known, long lived Presentation Model instead.
    2) To be honest, I would never use the ADO.Net Data Services, instead focus on well design WCF services and Data Contract.

  • Thanks for your response Fredrik.

    I agree with you regarding the Presentation Model.

    But wouldn't using DataBinding save us a lot of time?

    Also, would implementing DataBinding along with Presentation Model violate the pattern definition?


  • @Kunal:
    No, not at all.. I think the pattern is very suitable for data binding. In my post I gave two example, with and without data binding. Some peole prefer the manual binding, and some the data binding support.

  • That's great!

    Just one last thing. If i use a combination of Presentation Model and Repository Pattern in Silverlight then how do i go about with Asynchronous Calls to the WCF WebService?

    Or maybe i need to Expose the OnComplete Events?


  • @Kunal Shetye:
    About the OnComeplete event and async call. When the LoadFromPresentationModel is executed, the Async operation should take place, and there should also be a OnComplete event on the Presentation Model which we should hook up to know when the operation is completed and can bind the Presentation Model to the UI. I will add a post about this later to show how it can be implemented.

  • Hey Fredrik, thanks a ton.

    It just skipped my mind that i was leveraging DataBinding thus Async WebService calls wont hurt :)

    Eagerly awaiting your next post :)

  • The idea looks good, but I am not sure I like that the presentationmodel has the reference to repository to get the NameEntity. In many situations you may want to do some businesslogic on your Entity before you send it to the presentationmodel. So way didn't you have an constructor that took an NameEntity instead of the repository? Not saying you can't have both or one is better than the other, only courious!

    I tried another way for an presentationmodel for WPF and DDD, and that was to let my DomainEntity have an IPresentationModel interface (wanted to minimize the code) but since the databinding couldn't use Interfaces-properties but only took public property on the object that failed... not a correct DDD-approch but it would have saved me a lot of code...

    About the MVVM-pattern I found a weaknees I couldn't get around and that when I tried to implement a behaviorCommand for the OnClosing Event for a Form. No way in hell I could get that to work! So I hade to do a mix of MVVM and som classic form-event handling.


  • @Magnus:
    "The essence of a Presentation Model is of a fully self-contained class that represents all the data and behavior of the UI window".
    Earlier called Application Model in Samlltalk.
    The reason why I pass a Repository to the Presentation Model is to remove the loading and updating of the model from code-behind. Instead I let the Presentation Model handle the Loading and updating instead of letting the View handle it, but the View need to synchronize all the update to the Presentation Model. An alternative is to use the Supervising Controller pattern. Where a Presenter/Controller can be used. We can also create DTOs and make sure to have a controller which will use the Repository to get the model, and turn it into a DTO that is more suiteable for presentation purpose.

  • Excellent write up - thank you!

    I'm unsure however of your model/repository setup.

    Instead of:
    "_namePresentationModel = new NamePresentationModel(new NameRepository());"

    I'd expect
    _namePresentationModel = NameRepository.GetModel();

    and:

    "_namePresentationModel.Save();"

    NameRepository.Save(_namePresentationModel);


  • @Steve:
    Thanks for your comment, please see my answer to Magnus comment above.

Comments have been disabled for this content.