The WPF community seems pretty happy with the MVVM pattern for WPF development. I can see why. It’s a great fit for WPF and its strong data-binding support. It provides a very nice layer for managing UI state, translating, formatting, and aggregating data.

So let’s say that I adopt MVVM for my project. I think there are some scenarios that still need definition. One of these is “To Wrap or Not to Wrap?” Let me explain…

MVVM says that a ViewModel sits between the View (XAML) and the Model. The ViewModel (VM) exposes data from the model plus additional view-specific details that the view (V) can easily bind to. Ideally, the view can be constructed with zero code-behind. Pure XAML with bindings to manage data and UI state. This is all well and good.

Now, lets say that our model is reasonably real-world and has a entities that contain collections of other entities, which in turn contain collections of other entities. Maybe some of these even have references back to other trees of data. The classic example is customers and orders.

The Model:

Customer
    |_ Shipping Addresses (Collection)
    |_ Billing Address
    |_ Orders (Collection)
    |_ First Name
    |_ Last Name
    |_ Etc…

The Question:

I want to use MVVM, so I start working on the view models. I create one for Customer, start adding my properties and realize that I have a decision to make. Do I expose the model directly, or do I wrap each item in its own view model?

We have a couple options, and each has some consequences.

STEP 1: The Customer Object

Let’s start with the Customer object itself:

Customer has a bunch of data on it. The VM guidelines suggest that the VM should expose a property for each value on the model that it wants to expose. In this case, I want to show the first and last name on the view.

Option 1: Wrap Customer Model

To wrap first and last name, I create two new properties on the VM. One for each property. Being a good binding citizen, I make the VM support INotifyPropertyChanged and setup my property setter’s accordingly. (See my INotifyPropertyChanged Snippets post).

My model happens to support INotifyPropertyChanged too, and I want the View to know right away if the data changes in the underlying model. What to do? Looks like I need to add an event handler on my Customer instance’s PropertyChanged event. In that event, I need to check what property changed and bubble selected events via my VM’s own PropertyChanged event. Here’s the CustomerVM class so far…

using System.ComponentModel;
using System.Collections.ObjectModel;

namespace MvvmWrappers.ViewModels
{
    public class CustomerVM : INotifyPropertyChanged
    {
        private Models.Customer _Customer = null;

        /// <summary>
        /// Constructor - Add an event handler for PropertyChanged.
        /// </summary>
        public CustomerVM(Models.Customer customer)
        {
            _Customer = customer;
            _Customer.PropertyChanged += new PropertyChangedEventHandler(_Customer_PropertyChanged);
        }

        /// <summary>
        /// Watch for changes in the underlying model and propagate those that
        /// are exposed by this ViewModel.
        /// </summary>
        void _Customer_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "FirstName":
                case "LastName":
                    this.OnPropertyChanged(e.PropertyName);
                    break;
            }
        }

        /// <summary>
        /// Delegate the storage to the model.
        /// Also delegate the INotifyPropertyChanged handling to the model.
        /// </summary>
        public string FirstName
        {
            get { return _Customer.FirstName; }
            set { _Customer.FirstName = value; }
        }

        /// <summary>
        /// Delegate the storage to the model.
        /// Also delegate the INotifyPropertyChanged handling to the model.
        /// </summary>
        public string LastName
        {
            get { return _Customer.LastName; }
            set { _Customer.LastName = value; }
        }
        
        #region INotifyPropertyChanged
        ...
        #endregion

    }

}
 

Option 2: Not to Wrap

Let's say that I decide the above code is too much. So, I choose to expose the Customer model directly to the view. I keep the VM around though, because I may have other view related properties that I want to manage. These might include things like whether to expand or collapse the shipping addresses section. The VM is still valuable, but is not doing as much.

public class CustomerVM : INotifyPropertyChanged
{
    private Models.Customer _Customer = null;
    public CustomerVM(Models.Customer customer)
    {
        _Customer = customer;
    }

    
    private Models.Customer _Customer;
    public Models.Customer Customer 
    {
        get{ return _Customer;}
        set
        {
            if (value == _Customer)
                return;
            
            _Customer = value;
            OnPropertyChanged("Customer");
        }
    }

    #region INotifyPropertyChanged
    ...
    #endregion

}

 

Conclusions:

Where do we stand? Both options are viable (IMHO anyway).

The first options seems to be a more rigorous and “pure” implementation, but the cost is additional plumbing. In some cases, this is definitely justified. For example, I may want to have a property that exposes the full name in a single field. Here, the VM is very helpful and makes this task simple. However, there are many cases where the values are simply passed through.

The second option is simpler and seems more pragmatic. It says “I’ll add properties on the VM where they are needed, but I’m not trying to control all access to the model.”

In reviewing the sample application from the Caliburn framework, they implement the VM using option 2. The ViewModel exposes the model directly, including a number of child collections. The view then binds to both the model and the VM. This seems reasonable and simpler, but exposes the model directly to the view.

There are discussions of this question by others, but I don’t see conclusive answers. Ward Bell asks the question in his Birth and Death of MVVM Triads. The question is also asked on StackOverflow.

For me, the jury is still out. I prefer Option 1 because is it a bit more pure and clean. In the above case, the complexity is manageable. Things get more interesting in Part 2 of this post, where I’ll show some scenarios related to exposing a collection.

Cheers!