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

ViewModel INotifyPropertyChanged Code Generation

By , 14 May 2011
 

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

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
Member
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
 
-

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralRe: Code formatting sucks!!!memberColin Eberhardt14 May '11 - 7:29 
Hi,
 
This is a 'technical bog post' so is imported by codeproject automatically. It looks like the import process did a terrible job of the code formatting. I have now fixed this!
 
Regards, Colin E.
Colin Eberhardt
Twitter | Blog | LinkedIn

GeneralRe: Code formatting sucks!!!mvpKunal_Chowdhury14 May '11 - 7:33 
Yes, I know that it's a blog post and after the import you should format it properly. I also have posts fetched in CodeProject and those I did. This is require because those tagging formats are not supported by CP.

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

GeneralRe: Code formatting sucks!!!memberColin Eberhardt14 May '11 - 7:37 
OK - glad I am not the only one who has this problem.
 
Personally I think the articles codeproject creates from your blog RSS should be in 'draft' state. There is no notification of when your RSS feed is parsed, so an article can be left in a bit of a mess for a while. In this case I didn't even know it had been published, I changed my RSS feed settings without even thinking about teh fact that codeproject crawls it!
 
Colin E.
Colin Eberhardt
Twitter | Blog | LinkedIn

GeneralRe: Code formatting sucks!!!mvpKunal_Chowdhury14 May '11 - 7:40 
Yes and you will not know when it fetches the posts. Sometimes it takes 1 hour and sometime 1-2 days. I reported it to Chris and he pushed the services to a different server. You will be able to see them soon now.
 
If you have any suggestion for CodeProject, please use this forum: Site Bugs and Suggestions[^]

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

GeneralRe: Code formatting sucks!!!memberBenjamin Unanka16 May '11 - 2:45 
Now the article had been formated properly, one can fully grasp the point you are making.
i think the article is quite instructive as such i might want to reconsider my voting.Cool | :cool:
 
i give you 4.
 
Thanks
 
keep up the good work(s).
GeneralFormatting IssuememberJani Giannoudis13 May '11 - 11:00 
You have HTML tags in all <pre> blocks Smile | :)
Cheers, Jani Giannoudis

Latest article: Time Period Library for .NET

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

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 14 May 2011
Article Copyright 2011 by Colin Eberhardt
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid