ViewModel INotifyPropertyChanged Code Generation

This blog post describes a novel method of generating boiler-plate MVVM code using codesnippet automation. You simply add attributes to your view model classes and the code is generated for you!

Model-View-ViewModel (MVVM) has become the de facto pattern for Silverlight, WPF and WP7 applications, providing code that is easily tested and couples cleanly to the view via databinding. However, one small problem with MVVM is that it relies on the INotifyPropertyChanged (INPC) interface and the boiler-plate code which this entails.

This blog post describes a technique for implementing INPC and adding properties to your view model as easily as this:

[SnippetINotifyPropertyChanged]
[SnippetPropertyINPC(field = "_surname", type = "string", property = "Surname")]
[SnippetPropertyINPC(field = "_forename", type = "string", property = "Forename")]
public partial class PersonViewModel : INotifyPropertyChanged
{
}

There are hundreds of blog posts that describe solutions to the problem of implementing INPC including simple options like a base-class that implements the INPC interface, the popular approach of using lambda expressions and more complex solutions involving Intermediate Language Weaving (AOP), or dynamic proxies. However, for the sake of simplicity, most of the projects I have worked on have opted for a manual approach - with individual developers using codesnippets if they so wish.

There are a couple of problems with codesnippets, firstly they are not refactor friendly, secondly they do not reduce boiler-plate code, they simply provide a method for adding this code more quickly!

Yesterday I published an article on codeproject which describes a technique for 'automating' code snippets, where you indicate the use of a codesnippet declaratively via an attribute, with the resultant code being generated in a partial class. Here I am going to show how it can be used to streamline the creation of ViewModels and results in the removal of boiler-plate code.

The first step to using this technique is to add the CodeGen folder to your project. This folder includes a number of T4 templates (Visual Studio's built in code-generation framework):

With these templates added to your project, if you add a codesnippet to the project (i.e. a .snippet file), a corresponding attribute will be generated when the T4 templates are run. You can see in the above screenshot that a couple of snippets have been added and attributes generated.

The T4 templates are run when the project is built, or can be run on-demand by clicking the button indicated below:

So let's have a go at generating our view model code ...

We'll create a simple Person view model, which has properties of Surname, Forename and a dependent property of FullName which concatenates the two together. We'll start by adding the INPC implementation to our class via an automated snippet:

[SnippetINotifyPropertyChanged]
public partial class PersonViewModel : INotifyPropertyChanged
{
}

By adding the attribute above and compiling the code, you will find that a generated counterpart to our view model is created:

This file contains the code defined in our INPC codesnippet:

using System.ComponentModel;

namespace ViewModelCodeGeneration
{
  public partial class PersonViewModel
  {

    #region INotifyPropertyChanged Members

    /// <summary>
    /// Occurs when a property changes
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    /// <summary>
    /// Raises a PropertyChanged event
    /// </summary>
    protected void OnPropertyChanged(string property)
    {
      if (PropertyChanged != null)
      {
        PropertyChanged(this, new PropertyChangedEventArgs(property));
      }
    }

    #endregion
  }
}

We can now add a property to our view model:

[SnippetINotifyPropertyChanged]
[SnippetPropertyINPC(field = "_surname", type = "string", property = "Surname")]
public partial class PersonViewModel : INotifyPropertyChanged
{
}

Compiling the code and inspecting the generated file, we can see that the code has been generated based on the codesnippet that adds a property (with INPC PropertyChanged), based on the attribute parameters supplied above:

using System.ComponentModel;

namespace ViewModelCodeGeneration
{
  public partial class PersonViewModel
  {

    #region INotifyPropertyChanged Members

    /// <summary>
    /// Occurs when a property changes
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    /// <summary>
    /// Raises a PropertyChanged event
    /// </summary>
    protected void OnPropertyChanged(string property)
    {
      if (PropertyChanged != null)
      {
        PropertyChanged(this, new PropertyChangedEventArgs(property));
      }
    }

    #endregion


    /// <summary>
    /// Field which backs the Surname property
    /// </summary>
    private string _surname = null;

    public static readonly string SurnameProperty = "Surname";

    /// <summary>
    /// Gets / sets the Surname value
    /// </summary>
    public string Surname
    {
      get { return _surname; }
      set
      {
        if (_surname == value)
          return;

        _surname = value;

        OnSurnameChanged(value);

        OnPropertyChanged(SurnameProperty);
      }
    }

    /// <summary>
    /// Invoked when the value of Surname changes
    /// </summary>
    partial void OnSurnameChanged(string value);
  }
}

Finally, we add the second property, and add implementations for the partial methods that are invoked when either Surname or Forename changes, allowing us to implement FullName:

[SnippetINotifyPropertyChanged]
[SnippetPropertyINPC(field = "_surname", type = "string", property = "Surname")]
[SnippetPropertyINPC(field = "_forename", type = "string", property = "Forename")]
public partial class PersonViewModel : INotifyPropertyChanged
{
  public static readonly string FullNameProperty = "FullName";

  partial void OnForenameChanged(string value)
  {
    OnPropertyChanged(FullNameProperty);
  }

  partial void OnSurnameChanged(string value)
  {
    OnPropertyChanged(FullNameProperty);
  }

  public string FullName
  {
    get
    {
      return Surname + ", " + Forename;
    }
  }
}

All that's left to do is bind our view model to the view:

<Border BorderBrush="DarkGray" BorderThickness="4"
        CornerRadius="3"
        VerticalAlignment="Center">
  <Grid l:GridUtils.ColumnDefinitions="*,*"
          l:GridUtils.RowDefinitions="Auto,Auto,">

    <TextBlock Text="{Binding FullName}" FontWeight="Bold"
                Grid.ColumnSpan="2"/>
      
    <TextBlock Text="Surname:"
                Grid.Row="1"/>
    <TextBox Text="{Binding Surname, Mode=TwoWay}"
              Grid.Column="1" Grid.Row="1"/>  
      
    <TextBlock Text="Forename:"
                Grid.Row="2"/>
    <TextBox Text="{Binding Forename, Mode=TwoWay}"
              Grid.Column="1" Grid.Row="2"/>
    
  </Grid>
</Border>

(Note the simplified grid markup!)

Here's the code for this very simple example in action:

Get Microsoft Silverlight

This blog post has described a method for generating the boiler-plate code that the MVVM patterns requires. The use of T4 templates and partial classes mirrors the way that the Visual Studio designer generates code. Personally I think the end result is much easier to understand that the dynamic proxy or aspects / weaving approach described by others. The example given in this blog post is pretty trivial, but when you use it for bigger projects with complex view-models containing numerous properties, you really start to feel the benefit.

Furthermore, the technique described here can be used to automate any codesnippet! you can use it to generate dependency properties for example.

Enjoy!

You can download the sourcecode here: ViewModelGeneration.zip

For more information regarding how T4 / Env.DTE / XSLT are used to automate your codesnippets I would encourage you to read my codeproject article.

Regards, Colin E.

blog comments powered by Disqus