Annoyed with INotifyPropertyChanged?

By | August 14, 2013

Have you ever been annoyed with having to implement the cumbersome plumbing required for INotifyPropertyChanged ? Well, I have. So I tried to find a way to make authoring bindable objects better.

The typical example:

As you can see, it is quite verbose. The event and OnPropertyChanged() method need to be implemented for each class and it’s easy to get the implementation of OnPropertyChanged() wrong (typically introducing a race condition). Moreover, it’s 10 lines of code for each property. I hate that. The more you have to write, the bigger a surface for bugs to appear. A property should just boil down to   public string FirstName { get; set; } .

That won’t be possible of course. The default setters and getters just handle the assignment and loading of a compiler-generated backing field. So we somehow need to add the code for each property.

Enter Bindable objects

Similar to class NotificationObject, Bindable is here to help implementing INotifyPropertyChanged. The NotificationObject class only implements RaisePropertyChanged() but does not help with the implementation of the properties. Here is what you can do with Bindable:

Noticeably shorter, isn’t it ?

Behind the scene, Bindable uses a dictionary to store the property values. You probably have noticed that the property name is not given to Bindable.Get() or Bindable.Set(). Bindable leverages the compiler to provide the value automatically:

CallerMemberNameAttribute when applied on an optional parameter instructs the compiler to pass a string whose value is the name of the calling member. So when property FirstName calls Get<string>() , the compiler generates code for  Get<string>("FirstName") .

Here is the actual code for class Bindable:

Some aspects can be improved. For example, enabling subclasses to provide their own backing field. This is left as an exercise to the reader ;-)

I use this class a lot when implementing MVVM either in Wpf or Winforms.

What do you think ?

Edit: fixed code snippets as per Krumelur’s comments. Thanks Krumelur.

6 thoughts on “Annoyed with INotifyPropertyChanged?

  1. Krumelur

    B-R-I-L-L-I-A-N-T idea! However: I cannot get it to build :-( I tried VS2012 and Xamarin Studio.

    In the Set I’m getting:

    Error 1 The best overloaded method match for ‘Set(string, string)’ has some invalid arguments
    Error 2 Argument 2: cannot convert from ‘T’ to ‘string’

    Reply
    1. Krumelur

      Oh, just noticed: you’re missing code. That’s causing the build error. Set should probably be:

      protected void Set(T value, [CallerMemberName] string name = null) {
      Debug.Assert(name != null, “name != null”);
      if (Equals (value, Get (name)))
      {
      return;
      }
      _properties[name] = value;
      OnPropertyChanged(name);
      }

      Reply
      1. timoch Post author

        Krumelur, you are right. Apparently, I used a version of the code before I refactored it. I hit the same issue myself.
        Btw, sorry for the late reply, I was enjoying some hollidays :-)

        Reply
  2. peterthorpe81

    This is really cool I extended it to support IEditableObject using a second dictionary as a memento. That way I can cancel/save changes in winforms grids and similar.

    Its a shame there isn’t a [CallerMemberType] attribute we could use that could get us to just Get(); rather than Get<string>();

    Reply
    1. timoch Post author

      Applying memento here is a great idea. One could also easily implement undo/redo using snapshots or generate diffs for auditing/logging purposes. I think I’ll write a couple of posts on that. It’s been a while …

      Reply

Leave a Reply to peterthorpe81 Cancel reply