Click here to Skip to main content
Click here to Skip to main content

ViewModel INotifyPropertyChanged Code Generation

, 14 May 2011
Rate this:
Please Sign up or sign in to vote.
This blog post describes a novel method of generating boiler-plate MVVM code using codesnippet automation.

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
 
    /// <span class="code-SummaryComment"><summary>
</span>    /// Occurs when a property changes
    /// <span class="code-SummaryComment"></summary>
</span>    public event PropertyChangedEventHandler PropertyChanged;
 
    /// <span class="code-SummaryComment"><summary>
</span>    /// Raises a PropertyChanged event
    /// <span class="code-SummaryComment"></summary>
</span>    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
 
    /// <span class="code-SummaryComment"><summary>
</span>    /// Occurs when a property changes
    /// <span class="code-SummaryComment"></summary>
</span>    public event PropertyChangedEventHandler PropertyChanged;
 
    /// <span class="code-SummaryComment"><summary>
</span>    /// Raises a PropertyChanged event
    /// <span class="code-SummaryComment"></summary>
</span>    protected void OnPropertyChanged(string property)
    {
      if (PropertyChanged != null)
      {
        PropertyChanged(this, new PropertyChangedEventArgs(property));
      }
    }
 
    #endregion
 
 
    /// <span class="code-SummaryComment"><summary>
</span>    /// Field which backs the Surname property
    /// <span class="code-SummaryComment"></summary>
</span>    private string _surname = null;
 
    public static readonly string SurnameProperty = "Surname";
 
    /// <span class="code-SummaryComment"><summary>
</span>    /// Gets / sets the Surname value
    /// <span class="code-SummaryComment"></summary>
</span>    public string Surname
    {
      get { return _surname; }
      set
      {
        if (_surname == value)
          return;
 
        _surname = value;
 
        OnSurnameChanged(value);
 
        OnPropertyChanged(SurnameProperty);
      }
    }
 
    /// <span class="code-SummaryComment"><summary>
</span>    /// Invoked when the value of Surname changes
    /// <span class="code-SummaryComment"></summary>
</span>    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!)

You can see the code in action on my blog. 

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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Colin Eberhardt
Architect Scott Logic
United Kingdom United Kingdom
I am CTO at ShinobiControls, a team of iOS developers who are carefully crafting iOS charts, grids and controls for making your applications awesome.
 
I am a Technical Architect for Visiblox which have developed the world's fastest WPF / Silverlight and WP7 charts.
 
I am also a Technical Evangelist at Scott Logic, a provider of bespoke financial software and consultancy for the retail and investment banking, stockbroking, asset management and hedge fund communities.
 
Visit my blog - Colin Eberhardt's Adventures in .NET.
 
Follow me on Twitter - @ColinEberhardt
 
-
Follow on   Twitter   Google+

Comments and Discussions

 
GeneralMy vote of 4 PinmemberBenjamin Unanka16-May-11 2:45 
GeneralMy vote of 5 PinmvpKunal_Chowdhury14-May-11 7:41 
GeneralRe: My vote of 5 PinmemberColin Eberhardt14-May-11 7:42 
GeneralRe: My vote of 5 PinmvpKunal_Chowdhury14-May-11 7:44 
GeneralMy vote of 1 PinmemberBenjamin Unanka14-May-11 3:28 
GeneralRe: My vote of 1 PinmemberColin Eberhardt14-May-11 7:30 
GeneralRe: My vote of 1 PinmvpKunal_Chowdhury14-May-11 7:37 
GeneralRe: My vote of 1 PinmemberBenjamin Unanka16-May-11 2:40 
GeneralRe: My vote of 1 PinmvpKunal_Chowdhury16-May-11 3:11 
GeneralCode formatting sucks!!! PinmvpKunal_Chowdhury13-May-11 17:19 
GeneralRe: Code formatting sucks!!! PinmemberColin Eberhardt14-May-11 7:29 
GeneralRe: Code formatting sucks!!! PinmvpKunal_Chowdhury14-May-11 7:33 
GeneralRe: Code formatting sucks!!! PinmemberColin Eberhardt14-May-11 7:37 
GeneralRe: Code formatting sucks!!! PinmvpKunal_Chowdhury14-May-11 7:40 
GeneralRe: Code formatting sucks!!! PinmemberBenjamin Unanka16-May-11 2:45 
GeneralFormatting Issue PinmemberJani Giannoudis13-May-11 11:00 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140721.1 | Last Updated 14 May 2011
Article Copyright 2011 by Colin Eberhardt
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid