MVVM: Simple is Beautiful

It’s been a few weeks since I published the Simple MVVM Toolkit for Silverlight on CodePlex. Since that time I’ve fleshed out the documentation, which includes installation instructions and a programming reference.  I’ve also published an update that includes some additional helper methods and samples.  As I stated in my initial blog post, there are numerous approaches to implementing the Model-View-ViewModel pattern.  And while MVVM offers addresses issues such as maintainability, testability and designability – features required by any large scale Silverlight application – you should not attempt to implement MVVM without the aid of an MVVM toolkit.  A toolkit will usually include one or more base classes that provide support for things like data binding and async, and have a mechanism displaying modal dialogs, as well as a facility for locating view-models.

So the problem now is which toolkit to choose! That means you have to survey the half dozen toolkits that support Silverlight, compare their features, supporting documentation and samples, and then spend time learning how to use the toolkit.  All of this assumes you are already familiar with MVVM, which has its own learning curve and requires familiarity with basic aspects of Silverlight, such as XAML, data binding and commands. What’s a developer to do?

It was to address conundrum that I developed the Simple MVVM Toolkit for Silverlight.  Rather than try to compete with existing toolkits by including a bunch of features you might not even use, I decided to provide a core set of features that every MVVM application needs and to favor simplicity and pragmatism over architectural purity.  I also designed the toolkit to be a learning device for developers coming up to speed on Silverlight and MVVM, so the toolkit comes both with online documentation and a comprehensive sample application that has “before” and “after” versions and a ReadMe file with step-by-step instructions (I also intend to publish a screencast).

I want to emphasize how important it is to keep things simple.  A simple design requires greater forethought but is easier to learn and maintain.  A good example is deciding whether to bind the view to model entities or to completely encapsulate the model within the view-model.  At first glance it might appear that encapsulation would be a better design choice.  But it depends on how much control you have over the model.  If you are handed a pre-existing set of classes for your model, then wrapping the model in the view-model might make sense.  In this case you would create a property in your detail view-model for every property in your model that you want to expose.  That way, your view-model can look quite different than your model, perhaps aggregating several model classes and converting properties to what the view needs.

However, you need to keep in mind that this level of indirection comes at a price.  It means you have to replicate a lot of properties in your view-model that are identical to those of the model, which may not make very much sense if your model classes are not pre-defined and you do have control over their look and feel.  In fact, I would argue this is probably a more common scenario, especially if you are using a code-generation tool, such as a T4 template or a RIA Services domain context.  In this case it would make more sense to expose your model as a property on your view-model and let the view bind directly to it.  And this is the approach I take in my toolkit, which has a ViewModelDetailBase class that has a Model property set to the model that is exposed by the view-model.

This is facilitated by the fact that data binding in Silverlight is smart enough to use a property of a property.  For example, if I have a Customer model and a CustomerViewModel that has a Customer property, I can bind a textbox in the CustomerView like so:

<TextBox Text="{Binding Path=Customer.FirstName, Mode=TwoWay}" />

But let’s say I have a TextBlock that I want to bind to FirstName and LastName concatenated together?  The way to do this is for the view-model to expose a CustomerName property.

public string CustomerName
{
    get
    {
        // Concatenate first and last name
        return string.Format("{0} {1}",
            Model.FirstName, Model.LastName);
    }
}

The problem is that I need to have the TextBlock update when either the Customer FirstName or LastName changes, which means the view-model needs to subscribe to the PropertyChanged events of the model and in turn fire its own PropertyChanged event whenever the FirstName or LastName properties change in the model.  To support this scenario, ViewModelDetailBase has an AssociateProperties method that fires PropertyChanged for a view-model property whenever a model property changes.  To use it, all you have to do is call it from the Customer property setter in the view-model.

public class CustomerViewModel

: ViewModelDetailBase<CustomerViewModel, Customer> { public Customer Customer { get { return Model; } set { Model = value; // Associate model and view-model properties AssociateProperties(m => m.FirstName, vm => vm.CustomerName); AssociateProperties(m => m.LastName, vm => vm.CustomerName); AssociateProperties(m => m.IsActive, vm => vm.OrdersVisibility); } }

If you’re curious as to how AssociateProperties works, here’s the source code:

protected virtual void AssociateProperties

<TModelResult, TViewModelResult> (Expression<Func<TModel, TModelResult>> modelProperty, Expression<Func<TViewModel, TViewModelResult>> viewModelProperty) { // Convert expressions to a property names string modelPropertyName = ((MemberExpression)modelProperty.Body).Member.Name; string viewModelPropertyName = ((MemberExpression)viewModelProperty.Body).Member.Name; // Propagate model to view-model property change Model.PropertyChanged += (s, ea) => { if (ea.PropertyName == modelPropertyName) { InternalNotifyPropertyChanged(viewModelPropertyName); } }; }

Enjoy!

About Tony Sneed

Married with three children.
This entry was posted in Technical and tagged , . Bookmark the permalink.

12 Responses to MVVM: Simple is Beautiful

  1. Mitchell Lopez says:

    Do you have Vb.Net version of MVVmtoolkit..i can use it in my prject…

  2. Tony Sneed says:

    I uploaded a new version of the source code that can be used with VB.NET: http://simplemvvmtoolkit.codeplex.com/SourceControl/changeset/changes/11329. I will incorporate this into the next release of the toolkit. It was simply a matter of adding the CLSCompliant assembly attribute.
    Tony

  3. Adolfo says:

    Hi Tony,

    First of all thank you for putting this Framework together. It is the one I adopted due to the great documentation, simplicity and because I find it very complete. Now, I wanted to ask you if there is a way to propagate PropertyChange events from my Model to the ViewModel in a generic way. My Model classes already implement INotifyPropertyChangeEvents and my View is bound to the ViewModel. My ViewModel only exposes one generic object public property, but when I change that object properties programmatically I don’t see the associated UI element refreshing. I see you have an AssociateProperties method, but for that you need to specify the PropertyName in both your View and your ViewModel but I want to avoid that since the View is already specifying the PropertyNames in the Bindings. To be more specific, my View UI elements are bound to deep Model properties accessed through my VM generic object property. Any ideas?

    Thanks again,
    Adolfo

  4. Adolfo says:

    I think I already found my answer Tony. The problem was that all my model classes were explicitly implementing the INotifyPropertyChanged interface which breaks the PropertyChange event propagation from base types. As some experts suggested all of my model classes will have to inherit from a common base type, perhaps the ModelBase in your Simple MVVM framework.

    • Tony Sneed says:

      You got it. Your entity base class should inherit from ModelBase and NOT implement INotifyPropertyChanged. Likewise, each of your ViewModel classes should inherit from ViewModelBase. The toolkit comes with a Visual Studio item template that provides the boilerplate code for you. There is a Getting Started video and tutorial which should help you pick up the essential concepts.

      Note that the NotifyPropertyChanged method does not take hard-coded strings, but instead accepts a lambda expression for the property name, which provides a measure of type safety. This method also checks to see if you are on the UI thread and, if not, marshals the call over.

      • Adolfo says:

        Excellent, I will watch the videos and thanks for this valuable information. The problem I see now with inheriting from ModelBase is that my classes already inherit from other classes and C# does not allow multiple inheritance. How would you use the ModelBase class when having deep class hierarchies?. Like my example I have a Person base type and Employee which inherits from Person. I can make Person inherit from ModelBase but Employee can’t since it already inherits from Person and ModelBase is strongly typed so it doesn’t have access to local Properties…..

      • Tony Sneed says:

        If you inherit Person from ModelBase, then Employee can inherit from Person and does not have to inherit from ModelBase. As long as ModelBase is at the bottom of your inheritance hierarchy, then you don’t have to implement INotifyPropertyChanged from any of your classes and the protected NotifyPropertyChanged method will be available to all subclasses.

      • Adolfo says:

        Never mind. I already found my answer, here is how I implemented my property in my derived class (Employee):

        public String EmployeeID
        {
        get
        {
        return _employeeId;
        }
        set
        {
        _employeeId = value;
        NotifyPropertyChanged(m => this.EmployeeID);
        }
        }

        Before I was using NotifyPropertyChanged(m => m.EmployeeID); but m was refering to my base type Person so it didn’t find Emlpoyee property. But that simple fix took care of it. This will get me going now. Thanks again for all your help! I’ll keep having fun with your framework.

  5. Tony Sneed says:

    Yes, this will work. Person inherits from ModelBase, so m would show properties of the Person class, which is not what you want to do in the Employee class. To solve that, you need to call NotifyPropertyChanged(m => this.EmployeeID). Glad you’re on your way!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s