Model-View-ViewModel Overview

If you’ve spent much time working with WPF or Silverlight, you’ve probably run into the MVVM (Model-View-ViewModel) pattern before. It’s probably the most popular pattern for designing WPF/Silverlight applications. In this series of posts, I’m going to go over what I’ve found to be the best way to structure WPF applications. The first post is going to be a broad overview of my take on MVVM and what I’ve found works best. Further posts will dive deeper into each section and start to explain why I’ve made the decisions I have. Any feedback, questions, or comments are of course welcome.

The MVVM pattern has three layers: View, View Model, and Model. Each layer can access the layer beneath it, but not any layers above it. Layers View The View layer is your set of UserControls and code-behinds. The easy rule-of-thumb: if it needs to reference any WPF assemblies (such as PresentationFramework) or is in a code-behind then it’s part of the View. Data gets to the View from the ViewModel via Data Binding only. The View is 100% WPF-specific and would have to be entirely replaced if you decided to switch to a different UI technology (WinForms, Metro, ASP, etc). View Model The View Model is the “in between” layer that sits between the View. The View is data bound to properties on the View Model. It contains the logic to create other View Models and Models. The View Model is not WPF-specific. You should be able to instantiate and use the View Model from non-UI code such as unit tests (more on that later). Model The Model layer contains your business logic. If it involves reading from databases or representing domain-specific functionality, it’s part of the Model. Where does X go? When adding a new feature or component, it’s sometimes hard to figure out where exactly to put it. It’s not always obvious and often something could go any number of places. Selected Item If selection is actually used programmatically (such as a button to delete the currently selected item in a list box), selection should be bound in the View Model. This allows accessing and changing the item from both the View Model and the View. For example, you can bind the selected item in the View to show details or save and restore the selection when exiting and relaunching the application.

XAML:

<ListBox ItemsSource="{Binding Path=CartItems}"
        SelectedItem="{Binding Path=SelectedCartItem}" />

View Model:

public IList<ShoppingCartItem> CartItems { get { return m_CartItems; } }
public ShoppingCartItem SelectedCartItem {
    get { return m_SelectedCartItem; }
    set {
        if (m_SelectedCartItem != value) {
            m_SelectedCartItem = value;
            OnPropertyChanged("SelectedCartItem");
        }
    }
}

Drag and Drop

This is always a tricky one. I’ve only had to do it once in WPF. I ended up putting almost everything in the View, since you have to handle lots and lots of WPF-specific events and deal with stuff like finding elements in the visual tree and drawing the “ghost” that follows the mouse. I created a set of attached properties that attach the behavior on to the drag sources and destinations. The drag and drop events were then passed to the View Model as higher-level events after the drag was completed.

Document loading and saving

Documents in a document-based application are the Model. Loading and saving should probably be part of services that are injected into either the Model or View Model via DI. This lets you substitute reading and writing real files for fake files during unit tests. I’ve found this to work very well.

Loading from database

Part of the Model. Like loading documents, loading from a database should be a service that’s injected into the Model or View Model via DI. This helps with unit tests and design-time. For example, you could create a mock version of the database loader that returns a couple of sample items that you want to use when editing the View in the designer.

Input validation

Simple input validation is really easily to put into the View—WPF has basic support for doing things like parsing numbers. It’s also pretty easy to add on stuff using ValidationRules. From what I’ve found though, it’s better to move that stuff to the View Model. That makes it easier to unit test and allow invalid states. The View Model should then implement IDataErrorInfo to inform the View of invalid fields.

Application loading

I’ve generally gone for the simplest approach- View first. The first ViewModel is created using the dependency injection container in the code-behind for the first view (usually the application’s main window).

Dependency Injection

If you’re not familiar with Dependency Injection/Inversion-of-Control, Martin Fowler explains it well. DI makes setting up design-time/testing much easier. I’ve found it also replaces many uses of singleton static classes by allowing services to become injected pseudo-singletons instead.

Testing

MVVM is by far the easiest UI pattern I’ve seen for automated testing. I’ll cover this in a future post.

Design-time data

Another one of MVVM’s unique strengths is allowing you to see and even modify a semi-working version of your Views with real data in the Expression Blend and Visual Studio designers. See my previous post: WPF Design-Time data with MVVM

Further reading

WPF Apps With The Model-View-ViewModel Design Pattern Inversion of Control Containers and the Dependency Injection pattern