Blendable MVVM : Introduction and Databinding

Posted Thursday, September 10, 2009 by

This is the first post in a series about the Model, View, ViewModel pattern (MVVM), there are a lot of posts out there on this pattern and all seem to have a slightly different focus. The focus this series is going to take is keeping the pattern "Blendable" i.e. making sure we can take advantage of the tooling support in Expression Blend and that we don't interupt the designer / developer workflow.

I'm also not going to try and present the full system all in one step, we'll start simple and build up to a full working application.

MVVM is the presentation pattern du jour for WPF and Silverlight, it's also referred to as the "Presentation Model" pattern (from Fowler). Most people understand the Model and the View, but what the ViewModel defines can vary from developer to developer. For me the View Model is the Model of the View, it holds properties the View is bound to and commands the view invokes.

Since our ViewModel will be the source for data binding I'll need it to implement INotifyPropertyChanged, we'll do this on a base class, I also like to use Linq Expressions to generate property names, less magic strings.

public class ViewModelBase<T> : INotifyPropertyChanged where T : ViewModelBase<T>

{

    public event PropertyChangedEventHandler PropertyChanged;

 

    protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)

    {

        var propertyChanged = PropertyChanged;

 

        if(propertyChanged != null)

            propertyChanged(this, e);

    }

 

    protected virtual void OnPropertyChanged(params Expression<Func<T, object>>[] expressions)

    {

        foreach(var expression in expressions)

        {

            OnPropertyChanged(new PropertyChangedEventArgs(ReflectOn<T>.GetPropertyName(expression)));

        }

    }

}

The sample application we'll build is a cocktail browser, so our first simple view model will just display a list of cocktails, again for first article simplicity I'm using a synchronous data source (could be an embedded xml file) which is a hard coded list of cocktails. This'll be replaced with a WCF service in a later article.

public class CocktailService

{

    public IEnumerable<Cocktail> GetAll()

    {

        return new[]

        {

            new Cocktail

            {

                Id = 1,

                Name = "Black Russian"

            },

            new Cocktail

            {

                Id = 2,

                Name = "Fuzzy Duck"

            }

        };

    }

}

Our CocktailsViewModel will expose an ObservableCollection<Cocktail>, this can be a simple auto property as we the collection won't be changing, it's contents will. For this nice simple example we'll just be retrieving the cocktails from the data source and adding to them to the exposed collection. I've created a couple of extension methods to make this a little easier.

public class CocktailsViewModel : ViewModelBase<CocktailsViewModel>

{

    private readonly CocktailService cocktailService = new CocktailService();

 

    public CocktailsViewModel()

    {

        AvailableCocktails = new ObservableCollection<Cocktail>();

 

        var recipes = cocktailService.GetAll();

 

        AvailableCocktails.AddRange(recipes);

    }

 

    public ObservableCollection<Cocktail> AvailableCocktails

    {

        get; set;

    }

}

public static class ObservableCollectionsExtensions

{

    public static void AddRange<T>(this ObservableCollection<T> collection, IEnumerable<T> items)

    {

        if(collection == null)

            throw new ArgumentNullException("collection");

 

        if(items == null)

            throw new ArgumentNullException("items");

 

        foreach(var item in items)

        {

            collection.Add(item);

        }

    }

 

    public static void Replace<T>(this ObservableCollection<T> collection, IEnumerable<T> items)

    {

        if(collection == null)

            throw new ArgumentNullException("collection");

 

        if(items == null)

            throw new ArgumentNullException("items");

 

        collection.Clear();

        collection.AddRange(items);

    }

}

So now we have the worlds simplest ViewModel lets fire up Blend and take the role of the designer and hooking our layout to the ViewModel. This is my first attempt at a screen cast so lets see how well this works:

 

 

We're going to be doing what's been called "View First" MVVM, this simply means we'll be creating the View which in turn will create the ViewModel (we'll introduce Dependency Injection later on). Other approaches include "ViewModel first" or some third party (a "ViewManager" creating the pair).

So to begin with we'll create our view model as the DataContext for the UserControl using the property grid, we then simply bind our list to the AvailableCocktails via the "Explicit DataContext" tab under Data Binding. I'll also set the DisplayMemberPath to the cocktail's name.

We're now all done! In the next post in this series we'll have our view model created from Ninject and unit test the ViewModel.

kick it on DotNetKicks.com Shout it

Professional Windows App Development