Welcome to Pete Brown's 10rem.net

First time here? If you are a developer or are interested in Microsoft tools and technology, please consider subscribing to the latest posts.

You may also be interested in my blog archives, the articles section, or some of my lab projects such as the C64 emulator written in Silverlight.

(hide this)

Strategies for Improving INotifyPropertyChanged in WPF and Silverlight

Pete Brown - 16 December 2010

The Silverlight and WPF binding system is extremely powerful. With it, you can bind your UI to your viewmodels (or other backing objects), bind control values to each other (for example, a slider controlling an object's scale or rotation) all with little or no code.

In order for binding to work, it requires a little cooperation from code. The target of a binding statement (typically a property of some bit of the UI) must be a dependency property - that is, an implemented instance of DependencyProperty which can get its value from external sources. Similarly, the source of the binding must be able to notify that the value has changed. In the UI layer, this is typically a DependencyProperty, but in your non-UI objects, you'll need to implement INotifyPropertyChanged (often called "INPC") and raise an event whenever values change. Why? Because any class which has Dependency Properties must derive from DependencyObject, a constraint which makes no sense in entities, viewmodel and business-layer classes.

Basic, Verbose, INPC Example

Here's an example using INPC in a viewmodel class.

public class BasicApproach : INotifyPropertyChanged
{
private int _level;
public int Level
{
get { return _level; }
set
{
if (_level != value)
{
_level = value;
NotifyPropertyChanged("Level");
}
}
}

private string _lastName;
public string LastName
{
get { return _lastName; }
set
{
if (_lastName != value)
{
_lastName = value;
NotifyPropertyChanged("LastName");
NotifyPropertyChanged("FullName");
}
}
}

private string _firstName;
public string FirstName
{
get { return _firstName; }
set
{
if (_firstName != value)
{
_firstName = value;
NotifyPropertyChanged("FirstName");
NotifyPropertyChanged("FullName");
}
}
}

public string FullName
{
get { return FirstName + " " + LastName; }
}


public event PropertyChangedEventHandler PropertyChanged;

protected void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

Typically I'll refactor this so I have an abstract base class named Observable which contains the interface and event-raising function. Nevertheless, this code is tedious and error-prone. It's tedious because you have to expand properties which would have been fine as auto-props. It's error-prone because you need to pass the string name of the property to the event. If you make a typo or change the name of the property without changing the string, binding will never be notified that the property changed.

The string-based approach, however, was the best for the framework developers because it is flexible, very fast, and gives you the option to implement other approaches on top of it.

Other folks have come up with their own base classes, many of which include optimizations to avoid creating so many instances of the PropertyChangedEventArgs class and include helpful checking information using reflection when in debug mode. Here's an example from Josh Smith. One nice thing about Josh's approach is that takes a performance hit primarily when in debug mode, not release mode.

There are several other elegant approaches to solving this. Let's look at the common reflection and lambda approach first.

Using Reflection and Lambda Expressions

One particularly slick approach uses both reflection and lambda expressions to add in a compile-time check on the property name.

public class ReflectionLambdaApproach : INotifyPropertyChanged
{
private int _level;
public int Level
{
get { return _level; }
set
{
if (_level != value)
{
_level = value;
NotifyPropertyChanged(() => Level);
}
}
}

private string _lastName;
public string LastName
{
get { return _lastName; }
set
{
if (_lastName != value)
{
_lastName = value;
NotifyPropertyChanged(() => LastName);
NotifyPropertyChanged(() => FullName);
}
}
}

private string _firstName;
public string FirstName
{
get { return _firstName; }
set
{
if (_firstName != value)
{
_firstName = value;
NotifyPropertyChanged(() => FirstName);
NotifyPropertyChanged(() => FullName);
}
}
}

public string FullName
{
get { return FirstName + " " + LastName; }
}



public event PropertyChangedEventHandler PropertyChanged;

public void NotifyPropertyChanged<T>(Expression<Func<T>> property)
{
if (PropertyChanged != null)
{
var memberExpression = property.Body as MemberExpression;

PropertyChanged(this, new PropertyChangedEventArgs(memberExpression.Member.Name));
}
}
}

Now, as this does use reflection, it is much slower than the hard-coded version. You need to be very aware of this because the PropertyChanged event can be raised a large number of times in a class. You'll need to make a decision based on how you will use this in your project.

One optimization to this approach would be to cache the property descriptor information so you reflect on it only once. Another common optimization is to wrap all the code into a SetProperty (or similar) method (and this update) which handles the property value checking, assignment, and event raising.

In any case, the amount of code doesn't change significantly unless you use the SetProperty approach. What you've gained by this approach is compile-time checking of the property names - a non-trivial improvement. Another approach which gives us both the checking and the code reduction and which has gained traction lately is IL Weaving. This injects property changed information into the IL rather than into the source code.

Using IL Weaving

The ins and outs of IL Weaving is too much to include in this post. However, I want to refer you to Justin Angel's great post on the topic. Justin goes through from the top down to what it takes to use MSIL Weaving in your own project. Be sure to read the comments as well.

When using weaving, you can go back to using auto-properties and leave out all the INPC gunk. It does have its limitations, though. In the examples you'll find, it doesn't do anything for dependent properties like our FullName property. You can certainly expand the examples to include something like that, but I haven't seen it done.

Now, despite weaving not doing anything for our FullName property, that's a heck of a lot cleaner than the other approaches we've been using. It handles the majority of simple cases where the properties are not dependent upon each other.

Summary

There are tons of other approaches, including this interesting AutoPropertyChanged approach on codeproject and this post by Jonas on using a dynamic proxy and Ninject to do the dirty work. This post is by no means a survey of all of those, but instead a summary of a couple common approaches. I've seen some really slick implementations that go above and beyond what I've done here, so be sure to check them out. A simple bing search for INotifyPropertyChanged will show you a ton of examples.

In addition, most MVVM frameworks have taken one of these approaches and built upon it to make your life easier. That's one of the benefits of picking a MVVM framework when using that pattern with Silverlight and WPF.

The WPF team is also considering possible approaches for this. No promises, but it is on their radar :)

If you have a favorite approach I haven't mentioned here, feel free to link to it or describe it in the comments.

There's no downloadable source for this post on purpose. Don't use this code directly, instead go check out some of the more robust implementations out there. :)

           
posted by Pete Brown on Thursday, December 16, 2010
filed under:            

48 comments for “Strategies for Improving INotifyPropertyChanged in WPF and Silverlight”

  1. James Ashleysays:
    "Because any class which has Dependency Properties must derive from DependencyObject, a constraint which makes no sense in entities, viewmodel and business-layer classes."

    Pete,

    I'm under the impression that a VM that inherits from DependencyObject will perform better than one that implements INotifyPropertyChanged. Is that a mistake? Are there other shortcomings that make this a bad approach?

    James
  2. Andre Abrantessays:
    Great post, Pete !

    I'm still reading more about WPF (WPF 4 Unleashed, @AdamNathan), but for error-prone purposes, why not use a code snippet "propd" ?
    ...
    public int Level
    {
    get { return (int)GetValue(LevelProperty); }
    set { SetValue(LevelProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Level.
    // TODO: ownerclass is not defined
    public static readonly DependencyProperty LevelProperty =
    DependencyProperty.Register("Level", typeof(int), typeof(ownerclass), new UIPropertyMetadata(0));
    ...
    Thks !
    Andre.
  3. Guestsays:
    Well, my approach is, dont implement INPC at all, just bind with POCO.
    Of course it only works in certain limited scenarios, but my app falled well into the niche.
    It's an wpf app that uses data binding intensively but not a single line INPC stuff.
    The scenario is: your data is static when presenting on the UI,
    and any modification happens in the binded ui itself.
    for simple scenarios it just works, say you have a label and a textbox bind to the same property of a poco,
    user changing the text in textbox will be reflected to the label, with no need of INPC at all.

    the only case you really need INPC is that you modified the data directly from your backing code, then you need UpdateTarget().
    or something like adding/removing item from a collection, then you need a call to the ItemsControl.Refresh()

    but in most of cases the UI can work with a poco object without any help from code.
    you just need to design your data structure and logic to make it suitable for the UI to do the work it self,

    Example, a complex app config data structure, first you read it from anywhere, produce a poco,
    then bind it to an UI, show it to the user, now user can change it whatever he want.
    you back code would not need to change the object directly,
    then user pressed Save and closed the UI, then your code take the poco back to work with it.
  4. Hüseyin Tüfekçilerlisays:
    Check out NotifyPropertyWeaver http://code.google.com/p/notifypropertyweaver/ project which inspects your assembly and injects notification calls to properties of INPC-implemented classes. It's very simple to use, doesn't require you to ship any binaries with your app, has opt-in/opt-out mechanism via attributes (not required), detects inter-property references and fires necessary notifications, etc.
  5. Guestsays:
    OK I know the POCO approch breaks the MVVM pattern because you do need to control the UI directly.
    but thats rare cases, and the simplicity for not use INPC is quite worthwhile to break the pattern a littlle. :-)
  6. Guestsays:
    and the POCO approach is well suitable for business forms apps,
    where you grab some data, display them to user, user modify them through ui, you get your data back.
    as long as your data wont change automatically and dynamically in the background while presenting, your wont need INPC.
    a simple design rule for you POCO is: changing one property wont change another property.
    in other words, changing properties should be 'side-effects' free. ideally all properties are auto-props.
    as long as you data is static and plain, INPC is not needed. cheers !
  7. Petesays:
    @Andre

    That creates a dependency property, something which I consider out-of-place outside of the UI layer.

    @James

    You could, but it smells wrong to have such a UI-centric approach up in that position in the stack. It will make your viewmodel usable only in WPF (and Silverlight with a slight modification to the default DP approach), and will very likely make any tests more complex.

    Counter arguments are welcome :)
  8. Petesays:
    @Guest

    As long as you know the drawbacks. For example, if you show the same info in another part of the UI (like a treeview or list or something), you'll have to manually synchronize it after a change.
  9. Guestsays:
    Nope. I dont need to, as long as they are binded to the same DataContext.
    Just bind ListView to the collection and the the detailed info controls to
    the current item of the collection using the '/' syntax, it will get synchronized automatically.
  10. Petesays:
    @Guest

    Not if you change discrete properties in existing objects.

    Let's say you have a list of people on the screen. You click one and edit the spelling of the last name. With binding and INPC, that will get updated both in the field you're typing in, and the list displaying all the names. Without INPC (or something similar), you have to write code to synchronize the list with what is in the edit pane.

    Pete
  11. Guestsays:
    as I said above, you can bind a property to several different controls, as long as they get the binding from
    the same DataContext, all of them will be synchronized automatically, its all 2-way.
  12. Petesays:
    @Guest

    Not sure if we're talking about the same thing.

    When the user types into a textbox and changes the last name of an existing person, how are you getting that new last name, into the already-on-screen listbox without INPC, code, or a rat's nest of element binding?

    What you say about POCO and one-time display of data and single-UI field is fine. No argument there.
  13. Guestsays:
    My guess is, WPF will wrap a POCO DataContext into an INPC-ware wrapper, and use this as the actuall DataContext that controls uses.
    and it will wrap all the ref type properties of it too, and also items of collections.

    You can write some code and try it yourself.

    one caveat is, for TextBox the synchonize happens when you press enter or control loses focus, wont be realtime while you are typing. but its a modifiable behavior I think.
  14. Michael L Perrysays:
    There's also the strategy employed by Update Controls (http;//updatecontrols.codeplex.com). This library automatically discovers what the properties of your view model depend upon. It generates a wrapper that raises INPC whenever one of those precedent properties change.

    Consider your FirstName, LastName, FullName example. What if FullName was in the View Model, but FirstName and LastName were in the Model? Neither lambdas nor reflection would help you, because you want the View Model to raise INPC when the Model changes. Update Controls does that.
  15. Eduardosays:
    Guest have a point. I've recently changed to use MVP instead of MVVM and found that INPC is not really needed in most scenarios, and you can call NotifyPropertyChanged("") to refresh all bindings
  16. Petesays:
    For the record:

    XAML:
    <Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
    <Grid>
    <ListBox x:Name="PeopleList"
    Height="287"
    HorizontalAlignment="Left"
    DisplayMemberPath="LastName"
    Margin="12,12,0,0"
    VerticalAlignment="Top"
    Width="138" />
    <TextBox Height="23"
    HorizontalAlignment="Left"
    Margin="265,24,0,0"
    x:Name="LastNameField"
    VerticalAlignment="Top"
    DataContext="{Binding ElementName=PeopleList, Path=SelectedItem}"
    Text="{Binding LastName}"
    Width="120" />
    <TextBlock Height="23"
    HorizontalAlignment="Left"
    Margin="178,27,0,0"
    Text="Last Name"
    VerticalAlignment="Top" />
    </Grid>
    </Window>

    Code-Behind:

    public partial class MainWindow : Window
    {
    private ObservableCollection<Person> _people;

    public MainWindow()
    {
    InitializeComponent();

    _people = new ObservableCollection<Person>();

    _people.Add(new Person() { LastName = "Brown" });
    _people.Add(new Person() { LastName = "Fitz" });
    _people.Add(new Person() { LastName = "Hanselman" });
    _people.Add(new Person() { LastName = "Heuer" });
    _people.Add(new Person() { LastName = "Galloway" });
    _people.Add(new Person() { LastName = "Stagner" });
    _people.Add(new Person() { LastName = "Liberty" });
    _people.Add(new Person() { LastName = "Litwin" });
    _people.Add(new Person() { LastName = "Papa" });
    _people.Add(new Person() { LastName = "Guthrie" });

    PeopleList.ItemsSource = _people;
    }
    }
  17. Guestsays:
    OK :-)

    Accordig to this post, the binding system uses PropertyDescriptor the access properties of clr objects,
    so all the bindings will get notified when one changed the value throuph the descriptor object:

    http://social.msdn.microsoft.com/forums/en-US/wpf/thread/8e4f9b09-fd14-4be7-9d4b-f6038cd61e6d/
  18. Renaudsays:
    Pete,

    I am completely lost now ... I reproduced what Guest was saying and yes it works ... So now, I can update my fields without INPC ... Does it mean that what I was doing for so long is useless ? I don't know what to think anymore.

    Waiting for the result of your investigation.
  19. Bigsbysays:
    Hi, Pete & all,

    This is a very interesting discussion. I, mysefl, am always for minimizing the use of strings in quotes in code.

    @Guest is very correct but the title of the post ends with "... and Silverlight" and mind you that this effort in the WPF Binding engine to listen for property value changes is not present in its Silverlight congener.

    There is another option that I could not find the link to but I recall someone showing of Dependency Injection (IOC) that basically was something like this:
    - Override TypeDescriptor to make sure to anwser afirmatively when asked for the implementation of INPC and implement PropertyChanged event;
    - Use DI to catch the call on "set_*" methods and raise the event;

    This is error safe and performance-wise is also very nice because all this is ran only once on loading the first intance.

    I'll keep trying to find the link and, if I do, I'll post it.
  20. Bigsbysays:
    Now I begin to remember. It's all about Unity (http://unity.codeplex.com/).

    I couldn't find the actual media where I saw this but this should do it:
    http://msdn.microsoft.com/en-us/library/ff660851(v=PandP.20).aspx
    http://shecht.wordpress.com/2009/12/12/inotifypropertychanged-with-unity-interception-aop/
  21. pmontsays:
    @Pete and @Guest

    just dont forget about potential memory leaks

    http://support.microsoft.com/kb/938416/en-us

    and

    http://blogs.msdn.com/b/jgoldb/archive/2008/02/04/finding-memory-leaks-in-wpf-based-applications.aspx

    when not using DP's or INotifyPropertyChanged.
  22. Lex Lavnikovsays:
    @Sean Kearon,

    PostSharp introduces not-needed dependencies, generated code is really bloat.

    KindOfMagic and NotifyPropertyWeaver weave INotifyPropertyChanged ONLY.
    And do this transparently, optimal and fast, and main reason, EXTREME simple for end user.
  23. Bigsbysays:
    @pmont, If I read the MS support article right, the memory leak only happens when the target of the Binding is in the VisualTree of the source. If that is the case, there is no memory leak when the source of the Binding is not a Visual and/or not in the VisualTree.
  24. Big Nsays:
    Yeah, I've always assumed that what Guest was saying was well-know... that basically, if you do not modify the property from code then you do not need to call OnPropertyChanged.

    My solution to avoid using quoted strings in code was to add "Text" to any property that was to be bound to (displayed on the UI). Each POCO inherited from a class "NotifyPropertyChanged" that had a method that used relfection to call the PropertyChanged event on any property that had a name with "Text" in it. Any code that modified the property also called the described updating method from the POCO's base class.
  25. guestsays:
    well, never realized that there is a memory leak, maybe my app is too simple to show a significant imapct. :-(
    but the simplicity is still unresistable, jgoldb said clear the binding could help, maybe nullify the datacontext will also do ?
    will test is soon :-) thank you !

    for another comment, for those INPC resolution approaches, I think I prefer those ones that only happens just before you want to do the binding, afterwards you can remove the wrapper and go with pure data.
  26. Petesays:
    All

    I've put the post on why the POCO binding works, here: http://10rem.net/blog/2010/12/17/puff-the-magic-poco-binding-and-inotifypropertychanged-in-wpf

    There are performance and memory implications (plus the mentioned potential leak) when following this approach.

    Pete
  27. Tomsays:
    Personally I don't see what the big deal is with implementing INPC yourself. I've been doing it for awhile via a very simple base class and it doesn't seem like all that much to ask of the application developer. The biggest problem has probably been forgetting about certain properties that need to have their events raised at times, but that hasn't happened to me too often. Also like Eduardo said, being able to call NotifyPropertyChanged("") when refreshing all of the properties is warranted is also nice and convenient.

    The magic string issue seems overblown to me. If you want to rename a property, use the refactoring rename tool in VS, tell it to search strings, and use the preview. It does a fine job picking everything up. I will admit that if you make a typo, you can be screwed. That's still true for much of programming though, especially XAML work.

    Auto-properties would be nice, but it's not like the alternative is a huge complex chunk of code. It's still simple. So, they're a minor convenience to me. Once you throw XML docs in there, you're looking at at least a couple of lines of source code devoted to each property anyway.

    Even though improving on INPC seems like a minor battle in the grand scheme of things, it's always good to look for better ways, so I read through this post and the comments with great interest. IL weaving seems pretty sketchy, kinda like the nasty old abuses of the C preprocessor. Been there done that, glad we're beyond it with C#, would not consider this as a solution for a production app. Using a smarter base class that uses reflection and some tricks to avoid a performance hit in release build might be ok, if it's not too complex. The only other approach here that seemed possibly reasonable was Michael Perry's Update Controls, if it's as good as the web site says it is. I'm not convinced that the added convenience is worth the introduction of another dependency, but I'm thinking of taking a closer look at this one sometime.
  28. PKsays:
    Why can't we have something similate to
    public string FirstName {get; set; notify} ?

    .Net team is aware of the problems associated with manually writing all the boiler plate code associated with implementing INPC. They should do something about it.
  29. anonymoussays:
    Here are two interesting discussions about "Best Practices: How to implement INotifyPropertyChanged right?":

    1) http://compositeextensions.codeplex.com/Thread/View.aspx?ThreadId=53731

    2) http://compositeextensions.codeplex.com/Thread/View.aspx?ThreadId=54294
  30. guestsays:
    @PK, the language teams are very concerned when a core language feature is binded to a specific library / framework / type, so an attribute is more like it, but that's difficult too, I wont what 'Compiler as a Service' can bring us in this front.
  31. Garethsays:
    Thanks for this post. Not so much for the main topic, but as a Silverlight rookie who will have to learn very quickly as I have a few big projects lined up for next year, I've been searching all weekend for how to show calculated columns in a datagrid - at least one of the projects will use many of those! - and couldn't find anything.

    The class example at the top of the post answered my question nicely! So thanks! :o)
  32. Bruno Altinetsays:
    I would just like to address this bit, where you said the following for using expressions:
    "Now, as this does use reflection, it is much slower than the hard-coded version."
    There's a great performance comparison on the following link, and there really isn't that big of a performance impact, i'd even say it looks negligible to me
    http://www.pochet.net/blog/2010/06/25/inotifypropertychanged-implementations-an-overview/

    Is there something i overlooked here?
  33. John Rusksays:
    >If you have a favorite approach I haven't mentioned here....

    I have three ;-)

    1. The simplest is to pass null or String.Empty as the name of the "changed" property. This simply means "all my properties have changed", and it is very easy to implement. Having said that, it can feel a bit "wrong" sometimes.

    2. So I also have this: http://activesharp.codeplex.com which is much cleaner to write and simpler to read than the expression-based approach.

    3. There is also a third option, which is to use hard-coded property names, but to use unit tests to check that the property names are correct. I have posted details here: http://activesharp.codeplex.com/wikipage?title=Using%20ActiveSharp%20as%20a%20Unit%20Test%20Tool

  34. John Rusksays:
    @PK I made a similar suggestion to MS here, regarding extending the auto-property syntax, https://connect.microsoft.com/VisualStudio/feedback/details/332659/enhanced-automatic-properties

    But I have to (reluctantly) admit that they were right in turning it down. There is value in keeping the language simple (or at least, no more complex than it already is ;-)
  35. Eduardo Mardinisays:
    I have a post describin an IL weaving solution solving the problem of dependent properties.
    http://www.codeproject.com/KB/cs/INotifyPropertyChanged.aspx
    Thank you
  36. Emransays:
    The new C# 6 will let us get rid of both Hard Coded way and Reflection way. C# 6 will allow us to get a Property name using a nameof expression which will be a compile time evaluation for any member name.

    For example:

    public string Message
    {
    get { return _message ; }
    set {

    if(_message != value)
    {
    _message = value;

    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Message)));
    }
    }
    }

    You can find details at the following blog : 2 Most Exciting Features of C# 6 at http://www.spicelogic.com/Journal/C-sharp-6-most-exciting-features-9

Comment on this Post

Remember me