Click here to Skip to main content
15,880,503 members
Articles / MVVM

ViewModel INotifyPropertyChanged Code Generation

Rate me:
Please Sign up or sign in to vote.
4.94/5 (3 votes)
14 May 2011CPOL4 min read 25.7K   3   16
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:

C#
[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:

C#
[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:

C#
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:

C#
[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:

C#
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:

C#
[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:

XML
<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)


Written By
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

-

Comments and Discussions

 
GeneralMy vote of 4 Pin
Benjamin Uboegbu16-May-11 2:45
professionalBenjamin Uboegbu16-May-11 2:45 
GeneralMy vote of 5 Pin
Kunal Chowdhury «IN»14-May-11 7:41
professionalKunal Chowdhury «IN»14-May-11 7:41 
GeneralRe: My vote of 5 Pin
Colin Eberhardt14-May-11 7:42
Colin Eberhardt14-May-11 7:42 
GeneralRe: My vote of 5 Pin
Kunal Chowdhury «IN»14-May-11 7:44
professionalKunal Chowdhury «IN»14-May-11 7:44 
GeneralMy vote of 1 Pin
Benjamin Uboegbu14-May-11 3:28
professionalBenjamin Uboegbu14-May-11 3:28 
GeneralRe: My vote of 1 Pin
Colin Eberhardt14-May-11 7:30
Colin Eberhardt14-May-11 7:30 
GeneralRe: My vote of 1 Pin
Kunal Chowdhury «IN»14-May-11 7:37
professionalKunal Chowdhury «IN»14-May-11 7:37 
GeneralRe: My vote of 1 Pin
Benjamin Uboegbu16-May-11 2:40
professionalBenjamin Uboegbu16-May-11 2:40 
GeneralRe: My vote of 1 Pin
Kunal Chowdhury «IN»16-May-11 3:11
professionalKunal Chowdhury «IN»16-May-11 3:11 
Hello Benjamin,

Cool down. No one is attacking you. Don't know who gave you 1, but it was not from me. I only tried to explain you what happened during the technical blog fetch.

Regards - Kunal Chowdhury | Microsoft MVP (Silverlight) | CodeProject MVP | Software Engineer

New Articles on Silverlight 5 Beta:  Debugging Data Bindings in XAML | Working with Multiple Click (ClickCount)

Appreciate your Vote and Feedback

GeneralCode formatting sucks!!! Pin
Kunal Chowdhury «IN»13-May-11 17:19
professionalKunal Chowdhury «IN»13-May-11 17:19 
GeneralRe: Code formatting sucks!!! Pin
Colin Eberhardt14-May-11 7:29
Colin Eberhardt14-May-11 7:29 
GeneralRe: Code formatting sucks!!! Pin
Kunal Chowdhury «IN»14-May-11 7:33
professionalKunal Chowdhury «IN»14-May-11 7:33 
GeneralRe: Code formatting sucks!!! Pin
Colin Eberhardt14-May-11 7:37
Colin Eberhardt14-May-11 7:37 
GeneralRe: Code formatting sucks!!! Pin
Kunal Chowdhury «IN»14-May-11 7:40
professionalKunal Chowdhury «IN»14-May-11 7:40 
GeneralRe: Code formatting sucks!!! Pin
Benjamin Uboegbu16-May-11 2:45
professionalBenjamin Uboegbu16-May-11 2:45 
GeneralFormatting Issue Pin
Jani Giannoudis13-May-11 11:00
Jani Giannoudis13-May-11 11:00 

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

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