VM Workshop: Model View ViewModel (MVVM) and the Presentation Model Pattern in 5 UI Platforms

For some reason the family of design patterns that exist around the Model View Controller pattern seem to be an elusive band of characters. The first time I  encountered Model View Controller I studied the text hard trying to understand how the Strategy, Observer and Composite patterns worked together to accomplish some goal that – try as I might - remained fuzzy. Somehow I have a sense that I am not alone.

Model View Controller (MVC) is the parent pattern to a number of contemporary patterns that seem to find a natural home in Microsoft development. Variations of MVC have appeared over the years in an attempt to work within the construct of modern event-driven programming models. One of most distinguishing differences among MVC and some of the derivative patterns is that with MVC the controller executes first, where with the other patterns the view tends to execute first and then delegates control to some sort of “presentation” class.

VM Workshop Patterns

A few years ago I did a series on Model View Presenter (MVP) [Design Patterns Bootcamp: Model View * Patterns] in an attempt to discuss how to completely abstract away the user interface layer. MVP proves to be an effective pattern, but can be confusing to some with the heavy use of interfaces and events.

The recent popularity of XAML applications has brought focus to the Model View ViewModel (MVVM) pattern, which is technically a fine-tuned version of Presentation Model that takes advantage of .NET’s data binding framework. Further, the advent of ASP.NET MVC has created a strong push for some sort of presentation strategy into the realm of ASP.NET WebForms.

So this history lesson is great, but how do you do you write the code to implement the patterns?

Introducing VM Workshop

The VM Workshop is a simple reference application demonstrating the Model View ViewModel and Presentation Model pattern in a number of different UI platforms.

The project includes examples in:

  • Silverlight
  • WPF
  • WebForms
  • ASP.NET MVC
  • Ajax
  • WinForms

…and as an open source project, you are invited to help add examples of how to deal with a myriad of different UI use cases!

The purpose of the VM Workshop is to be a working programmer’s reference, not an exposition in pattern purity. Therefore you may see small details that may not fit the textbook definition of the patterns, but the point is to provide a template for effective pattern use. For instance there is an example in ASP.NET MVC is included in VM Workshop. Obviously the pattern being implemented is Model View Controller, but the construction of a “view model” class is still relevant in this context. While referring to ViewModel class in a ASP.NET application may be technically inappropriate, I use the term “view model” to interchangeably refer to a ViewModel or Presentation Model class for simplicity.

I recently messaged John Gossman, arguably one of the most visible proponent of MVVM, to ask whether or not MVVM is exclusive to XMAL applications or if the pattern may be applied to any UI platform. John replied saying:

I think the pattern is completely applicable to any UI technology.  There are some details around the use of commands and data-binding that tend to be XAML specific, so I tend to use MVVM for the XAML version of the pattern and to keep from having religious wars with Patterns zealots.  The more general pattern is called PresentationModel by Fowler.  OTOH, one of the nice things is if you design your Model and ViewModel’s correctly you should be able to reuse them between XAML-based and other UI technologies.

VM Workshop is meant to be a learn-by-example project showcasing different styles of implementation.

Examples in C# and VB.NET

Often discussions surrounding design patterns tend to only be available in C#. In order to extend the conversation to as many developers as possible, I’ve include a VB.NET solution that operates in complete parity to the C# version. The only difference in the VB.NET version is that due to lack of lambda support some of the places AutoMapper is leveraged in the C# version are removed and objects are mapped manually.

A Grid, a Form and an Action

The initial example is provided for all the UI platforms. Each implementation features the same UI and workflow composition. First a grid is presented to the user:

Grid

Upon selecting an individual item, an edit form becomes available allowing the user make changes to the item:

Form

Note: These screen shots here are taken from the WebForms sample, but the UI reflects the appropriate look for each of the respective UI technologies.

Once changes are complete, and the ‘Save' button is pressed, the persistence operation is initiated. After persistence is complete, each implementation tells the UI to how to response respond to the action.

Please note that true persistence is not implemented in VM Workshop. In an effort to avoid using a database (which keeps the code more portable) persistence functions are simply stubbed out in the code. In the end, the project includes the same messages that would be sent among the application layers in any real-world application.

Minimizing Code in the View

The motivation for using these patterns is often creating a more testable user interface layer, decoupling your application from UI technologies or perhaps to promote better application composition. No matter what the motivation, the overarching goal is to remove application logic from the view layer. The examples in VM Workshop use a number of general concepts to achieve a thin view.

Lazy Loading

The grids are populated through a lazy loaded property on the view model class. This ensures that the request for data is restricted to only the times when the data wasn’t previously prepared. Another benefit is that a call to somehow ‘get stuff’ is not required. When the grid binds to the 'Products' property the property’s implementation knows where to get the data if it doesn’t have it.

Visibility Properties

Visibility properties (in XAML implementations) or boolean properties on the view model classes are used to control whether or not controls, messages or other UI elements appear to the user. Binding the state of these properties to the appropriate elements on the screen relieves the view of having to decide what is shown to the user and what is hidden.

No Logical Operations

While taking great care to remove all logical operations from the view, even seemingly benign tasks such as casting input into primitive types is delegated to the view model or some other class for execution. Even simple operations like type casting can quickly cascade into a series of business rules. Consider how convoluted validation scenarios can become when the application is expecting a currency value, but is one way or another served a string. While the validation does have UI implications, this type of logic is best handled in a lower level than the view.

Presentation Objects and Data Transfer Objects

The use of presentation objects or data transfer objects, or DTOs, (I tend to flip between terms depending on my mood) is used to accomplish at least two goals:

  1. Hide the domain model from the rest of the application. Concealing the full-fledged Products class from the view makes sure unnecessary pressure is not exerted on the model to mutate at the whim of the view.

  2. Make custom mapping the responsibility of the type. The presentation object’s job is to prepare the data coming from the domain model into a form that is natural to the view. This mapping or conversion responsibility is best placed in the hands of the presentation object and not within the procedure of an operation.

Get Acquainted

Check out the video that will get you oriented with VM Workshop:

Get Involved

The code for VM Workshop is available on CodePlex and you are encouraged to submit your implementations into the workshop!

Resources

VM Workshop uses nBuilder create data objects and AutoMapper for DTO to domain object mapping.

Thanks

Thanks to Infragistics for providing the time to develop the VM Workshop.

13 Comments

  • When I edit a product, the changes do not appear in the grid. Is this a feature you are intending to add? I think that UI updates are an important part of the MVVM pattern.

  • In the WPF example you set the DataContext in code; could this be done in the XAML, or does it not provide a way to pass in the instance of the repository? Or... an opportunity to use DI to resolve the repository?

  • @Michael: You are right that UI updates are important. I started working on an implementation for web persistence that works with the data objects - so yes this is something I plan to add.

    @John: It's possible to create an instance of the ViewModel in XAML, but the code behind would still need a reference to the class to do the delegation. Of course you could reference it through the page's Resources and then cast it, but the current approach just seemed simpler. I'd like to make another WPF example that uses commands - then instantiating the ViewModel in XAML would make more sense.

  • Hi Craig,

    I downloaded the workshop today and was looking specifically at the implementation differences between WinForms and WebForms. I modified the ViewModel classes so on my version the two implementations are identical.

    Shouldn't this effectively be the goal? What impact do the different UI platforms have on the VM? Shouldn't we be able to port the same Model and ViewModel to different Views?

  • I don't see my previous comment yet, but thought I would follow up on it. Although, it seems to be "working", there are potential problems with the changes I made to the web forms approach. Before saving, to be certain we are updating the correct object, we should call GetSelectedObject on the VM.

    Old aspx.cs was:
    ProductEditView view = new ProductEditView();
    view.Description = this.description.Text;
    view.Price = this.price.Text;
    view.ProductId = this.productId.Value;
    view.QuantityOnHand = this.quantityOnHand.Text;
    view.ReleaseDate = this.releaseDate.Text;
    view.Title = this.title.Text;
    this._vm.PersistChanges(view);

    New is:
    this._vm.GetSelectedProduct( this.productId.Value );
    _vm.SelectedProduct.Description = this.description.Text;
    _vm.SelectedProduct.Price = this.price.Text;
    _vm.SelectedProduct.ProductId = this.productId.Value;
    _vm.SelectedProduct.QuantityOnHand = this.quantityOnHand.Text;
    _vm.SelectedProduct.ReleaseDate = this.releaseDate.Text;
    _vm.SelectedProduct.Title = this.title.Text;
    this._vm.Persist();

  • How to make a specific control invisible in view from MV(model View) control?

  • I'm not sure the whole .Net developer base is ready for all this cute overhead of a full ViewModel wrapper around a Model just to present their View. It sure adds a lot to the complexity. There are plenty of mid-sized apps being built every day where a few additionally needed "presentation properties" can be packaged in a ViewModel wrapper around the Model to *supplement* the Model properties, but not a total re-hosting of every single property. This way, most of the UI binding is against the ViewModel.Model properties, and a few bindings can go against the ViewModel supplemental presentation properties.

  • @FreshPrice: Thanks for your code I will look at adding it to the project

    @N: The examples show you how to make controls invisible by binding to a property in the ViewModel

    @Matt Slay: First of all I don't pretend to know what is best for the entire .NET developer base :)

    It seems to me that developers should learn as much as they can about different techniques in order to make the best choices for the situation. The VM Workshop is simply a reference for those willing to learn MVVM/Presentation Model. If it's not for you, then no big deal.

    As for added complexity, I suppose it depends on your perspective. Personally, I think it makes things simpler. Having a centralized place to prepare the model for your view, which is disconnected from the UI layer can open your development practices up to many advantages. Certainly for very small applications this may not be the advised approach, but I think the case has been stated many times over about the virtues of abstracting your view for testing and breaking dependence on a UI layer.

  • I really like the workshop, because it shows how these ideas can be used in different technologies.

    However, I don’t really understand why the DTOs belong to the domain “layer”? In my opinion they are somehow dependent on the presentation – as implied by the term presentation objects. So why they are not part of the view model “layer”?

  • Any plans to release a VS2010 version?

  • yes, in fact there are a number of updates I want to make to the project. Stay tuned :)

  • Good morning,

    I just downloaded your VM Workshop (VB version). There's a reference to an "Automapper" namespace in several files that I can't seem to find. It's preventing the solution from building. What am I missing?

  • @k4gdw:

    you need the DLL from

    http://automapper.codeplex.com/

    not sure why it's breaking on you...

Comments have been disabled for this content.