Click here to Skip to main content
15,881,588 members
Articles / Programming Languages / C# 4.0
Article

Dynamic INPC, Clean INPC

Rate me:
Please Sign up or sign in to vote.
4.93/5 (8 votes)
28 Mar 2011CPOL15 min read 36.3K   336   29   5
A look into dynamic as a way to automate INotifyPropertyChanged implementation. An alternative approach on using INPC in ViewModel.

DynamicINPC.jpg

Introduction

The first part of the article shows a simple way to free a ViewModel in the MVVM pattern from infrastructural code by using Dynamic Extensions in C# 4.0. The second part of the article raises some questions on whether we need to eliminate INPC in the first place and suggests a little different approach in writing ViewModel classes.

Background

It is well known among WPF/Silverlight programmers that data binding is the main driving force of UI in WPF or Silverlight. Its ubiquity gave birth to the Model-View-ViewModel, or MVVM, pattern. While MVC has been here for a while (but rarely in the WinForms world), the excellent data binding support in WPF provided that pattern almost 100% acknowledgment as a main tool in building UI for WPF and Silverlight applications. Let me remind you the whole idea of MVVM (you can skip to the next paragraph if you do not want to hear it once again :)).

Suppose you have a large domain model somewhere more close to your storage system (or inside it) that implements all the rules and logic of your domain. It's big. For a specific screen, or View, you only need a small part of that domain business logic.

To improve user experience, you also would want to provide some validation close to the user before you send commands to the domain model. You probably have some logic that is only UI specific, like "disable controls while I am saving changes". And we want this to not be the part of the View, because... well, because it hurts testing, for example.

So, we implement this logic in a distinct class to provide readability, ease of maintenance, and unit tests of our View. For the UI controls, we leave the responsibility of gathering the user's clicks and typed keys, but the logic of interaction with the user goes to a separate, simple, testable class which models the View, hence ViewModel.

There are a lot of UI patterns that do exactly the same. Where the MVVM differs is that it uses specific data binding mechanics provided by WPF/Silverlight. Since these mechanisms are not an abstraction but rather an implementation, one could say that MVVM is not really an architectural pattern but a technological one. And one would probably be right. At least its author, John Gossman, called it MVC for WPF (I like abbreviations! They sound so professional. :)).

And here lie some problems, or better to say, nuisances.

MVVM Nuisances

Since MVVM relies on specific technology to work, it should be implemented in a way that this technology, i.e. WPF data binding, understands. Those are: INotifyPropertyChanged interface implementation (INPC for short); DependencyProperty; providing a XXXChanged event for each property with the XXX name. You can also implement ICustomTypeDescriptor or use a custom TypeDescriptorProvider with your View Model.

Among these methods, the most popular choice is the implementing of INotifyPropertyChanged. Although there are a lot of reasons to use it instead of other methods, one of the biggest advantage of it, in my opinion, is the fact that it sits in a sweet spot between “too noisy to read” (DependencyProperty, XXXChanged event for each property) and “too complex to write” (Type Descriptors).

But it’s not ideal either, and a lot of effort has been made to overcome its disadvantages. One of those is the fact that a notification event uses strings to communicate with the View. On the notification side, it can be solved quite easily, by using the “static reflection” technique, which allows raising notifications in a strongly typed manner. But this does not help much on the consumer side since WPF data binding is not strongly typed either. (Note that this is the real problem because the person who maintains the View probably doesn’t even know that you renamed the property). To mitigate that, you could create a unit test that would compare XAML bindings with the ViewModel properties. It's not that hard, but it is out of the scope of the subject of the current article.

This article is about the other disadvantage of INPC. It's not a disadvantage per se, it's just a nuisance. The implementing INPC brings a lot of infrastructural code to your ViewModel which is not connected to logic itself. It's annoying to write and it's a distraction to read. Although many consider this not a big deal (and I tend to agree with them), removing or simplifying the INPC implementation is one of the most popular requests for future improvements in WPF/Silverlight.

Many approaches have been used to downplay this annoyance. Aspect orientation; using a special class to represent the property (which implements INPC); code generation - you name it. All those approaches do a similar job - they clear the ViewModel from infrastructural code and implement this infrastructural code by some external mechanism. You should always remember though that by doing this, you effectively remove the ability to fine grain your notifications. I will return to this later, but for now, let's suppose that we really hate implementing INPC and want to automate this process somehow. Now, without further ado, here is yet another method to free our beloved View Models from the INPC infrastructure.

Best ViewModel ever?

What would the prototypical "pure" ViewModel look like? Probably, something like this:

C#
public class FindAnswersModel
// No INotifyPorpertyChanged implementation
{
   // 1. Calculations 

   // keeps state for argument 1
   public int Argument1 { get; set; }

   // keeps state for argument 2
   public int Argument2 { get; set; }

   // reports calculated value
   public int Total { get { return Argument1 + Argument2; } }

   // 2. Commands (no ICommand infrastructure)

   // command itself - just public method 
   public void FindAnswer()  // command
   {
      CurrentlyFindingTheAnswer = true;
      try
      {
          FindingAnswer();
          _log.Add(DateTime.Now);
          SelectedLog = Log.LastOrDefault();
      }
      finally
      {
          CurrentlyFindingTheAnswer = false;
      }
   }
   
   // private method that does real job which
   // probably just calls for external service
   private void FindingAnswer()
   {
      // finding the answer could take 7.5 million years
      Thread.Sleep(5000);
      Argument1 = 42;
      Argument2 = 54;
   }

   // reports if command can be invoked   
   public bool CanFindAnswer { get { return !CurrentlyFindingTheAnswer; } }  
   
   // reports if view model is busy now finding the answer
   public bool CurrentlyFindingTheAnswer { get; private set; }    

   // 3. Collections
   
   // reports how view should see collection of log entries (ordered)
   public IEnumerable<DateTime> Log { get { return _log.OrderBy(x => x); } }
   
   // keeps pointer of selected log entry (for selectors)
   public DateTime SelectedLog { get; set; }
   
   private IList<DateTime> _log = new List<DateTime>();
}

I called that class ...Model but it does not really matter. I just wanted to emphasize the fact that it does not implement INotifyPropertyChanged or any other mechanism for Binding. Still, it's a View Model in a sense that it models what this specific View is doing. It is not a domain model. But it is pure POCO, no notifications attached. Now, how could we attach this model to the View and ensure they start to chat with each other? The answer proposed in this article uses the main feature of C# 4.0 - Dynamic Extensions.

Enter DynamicObject

Let's try a slightly different aproach. What if we create some wrapper to our Model that would implement INPC and would be bound to the View instead of our Model class? It could update the properties of the Model class through Reflection, it could raise the PropertyChanged event on behalf of the underlying Model. Until now, however, it was not a good approach because you could not mimic the property structure of the underlying classes at runtime. (Except for through AOP, of course. But, to be honest, C# is not very friendly to the AOP paradigm. You should bring dependency on the external library, your properties should be virtual (and this feels quite weird), you should decorate them with attributes... it's just too much infrastructure to remove infrastructure!)

But now, since the introduction of Dynamic Extensions in C# 4.0, we can do it pretty easily. We can bind DynamicObject to our View and now binding starts to request those property values (by its name) from TryGetMember and sends values back to TrySetMemeber of the dynamic object. And there we can intercept them and pass them to our real Model. Turns out that it is very easy. Here is how to make it.

First, we inherit our wrapper from DynamicObject and implement the INotifyPropertyChanged interface (I called this wrapper ViewModel). We pass our Model object to this wrapper and keep it there to assign values to real properties.

C#
public class ViewModel : DynamicObject, INotifyPropertyChanged
{
    protected object TheObject { get; set; }
    public event PropertyChangedEventHandler PropertyChanged = delegate { };
}

Then we override two methods:

C#
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
  ICommand cmd;
  // this is utility method - see the source 
  PropertyInfo prop = GetProperty(binder.Name);
  result = prop.GetValue(TheObject, index: null);
  return true;
}

public override bool TrySetMember(SetMemberBinder binder, object value)
{
  // this is utility method - see the source
  PropertyInfo prop = GetProperty(binder.Name);
  // if you use correct ValueConverter for binding in View
  // this automatic type change and try catch is not needed
  try
  {
     prop.SetValue(TheObject, Convert.ChangeType(value, prop.PropertyType), 
                   index: null);
  }
  catch 
  {
     prop.SetValue(TheObject, value: null, index: null);
  }
  NotifyUI();
  return true;
}

As you see, the Set method automatically calls the notification of the UI after any change, because any change potentially changes other properties. Let me stop here a little. This NotifyUI() method may implement some kind of smart strategy to notify on changes. For example, we probably should not notify back that the property prop has changed. We might store the original values of properties and send notifications only for those properties that have really changed. But, in most cases, it is good enough just to send notifications for all properties. It worked in WinForms, and WPF is even smarter in handling only real changes. What about performance? Well, it's enough in most cases. In the example provided with this article, you could see that 100 properties are being updated every 100 ms without any delays. Of course, if you have 10000 properties, you probably should not use that. But probably, you should also reconsider what you are doing in the first place.

What we should really think about though is avoiding cyclic notifications. Since notifications are sent automatically, it really can happen. That is why I made a simple guard by keeping a list of the currently notified properties. Here is the code:

C#
HashSet<PropertyInfo> beingNotified = new HashSet<PropertyInfo>();
protected void NotifyUI()
{
  foreach (var prop in TheObject.GetProperties().Where(
           x => false == beingNotified.Contains(x)))
  {
    beingNotified.Add(prop);
    PropertyChanged(this, new PropertyChangedEventArgs(prop.Name));
  }
  beingNotified.Clear();
}

Of course, it is not real code. Real code does a little caching for Reflection to avoid the big cost of looking up PropertyInfo. You could see it in the attached example.

But what if we want to notify on changes from inside our Model? From what I told you before, you can san see that all notifications have been initiated by the user's action. And although for MVVM it is almost 90% of all cases, sometimes you really need it in a different way. Say, to show a user how much time she has spent in the View by changing the time property. The apparent answer is that you can send notifications through this wrapper. To accomplish this, the ViewModel class keeps a list of weak references to all of its created instances. So, you can ask from inside your Model to notify like this:

C#
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(1);
timer.Tick += (s, e) =>
{
  Seconds++;
  ViewModel.UpdateFor(this);
};
timer.Start();

And this is probably it, and it works pretty well. But wait a minute, what about commands? Let me digress a little and tell you that personally, I think that the whole ICommand story is not very MVVM-ish. Commands were invented before MVVM, and that's why the first thing you do when starting to use MVVM is implement your own Command class. Or, you bring the DelegateCommand implementation into your code. But let's ask ourselves; is clicking a Button or a Menu the only way allowed to call methods in a ViewModel? What about right clicking on the canvas in some area? Or pressing Enter in the text box? The correct way would be to direct the map of the control event to the method in the ViewModel. Luckily, it can also be done within the current framework (let's thank John Gossman for another term - attached behavior), but this is out of the scope of the article now.

For now, let's use commands. We can ask ourselves what does it mean - to bind to command. Really nothing more than to bind to any other property. In other words, when the Button binds it Command property to Path="FindAnswer" it just requests the same TryGetMember of our dynamic class to provide the property of type ICommand with the name FindAnswer. So, we can just create commands for each public method of the underlying model and return the correct command when requested. The Button would be perfectly happy after that. Here is a modification of the TryGetMember implementation to support commands:

C#
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
    ICommand cmd;
        if (_commands.TryGetValue(binder.Name, out cmd))
        {
            result = cmd;
                return true;
        }

        PropertyInfo prop = GetProperty(binder.Name);
        result = prop.GetValue(TheObject, index: null);
        return true;
}

Please, see the real code in the example to find how this _commands dictionary is created and populated.

Before I finish, I'd like to mention one more thing. We could continue to use our original Model as a data context at Design time to see what properties we have to bind (without Commands though, sorry, they simply don't exist in the original class). In the runtime though, we replace the data context with a DynamicObject wrapper and the View would see no difference. Except, it will start to receive notifications happily ever after.

Now, let me backup a little and ask if you have some hesitations. Probably you do. Probably you feel a little uncomfortable losing control of when and for what you send those notifications. In fact, after implementing all this, I had the same feelings. And that brings me to the last part of the article.

Should we automate notifications at all?

Let's ask ourselves a simple question - why do we need those notifications in the first place? For example, you have a Description property. You probable bind it to either TextBox or TextBlock. You probably load values into the View Model before you attach it to the View's data context. (I am not sure if you do, but it is usually cheaper to replace the whole data context at once than to send first notifications, property by property). So TextBlock is probably covered because it loads the value from the Description when the data context is assigned without any notifications. But even if your use of ViewModel is different, it does not really matter (more on this later).

What matters is that the TextBox updating its source is also covered. TextBox knows what it is bound to. It should be perfectly fine to update the ViewModel property without any INotifyPropertyChanged. And you know what? That is exactly what it does. Moreover, WPF makes an extra step and updates other controls that are also bound to this property. Somehow, it is a little known fact, but you should not implement INotifyPropertyChanged to have simple two-way binding (another little known fact about Binding is that it handles a cross-thread raise of PorpertyChanged event just fine). Anyway, to test it, create a simple class with a string property and bind it to a TextBox and next to it, to a TextBlock. You will see that the binding works just fine without any INotifyPropertyChanged implementation. Changes in the TextBox are going back to the property value and are reflected in the TextBlock.

Then why do we implement it? As the name suggests, we need it to report back to the UI when something is changed outside of the View controls. Data is loaded from a database. Calculated properties change their values. Timer updates the time spent property. We started some process and want to notify the UI on its result when it finishes. You probably already guessed what question I will ask next...

Why do we raise notification in the property's own setter?

I know the answer - we tend to encapsulate the behavior inside the setter. And notifying that a value has changed is a good candidate for this encapsulation. Except that in the case of the ViewModel class, it does not make any sense. The ViewModel is intended to be bound to controls. Controls change those setters. They know it without notifications. From what we see, those two classes will do absolutely the same job as a ViewModel.

C#
public class CalculatorViewModel : INotifyPorpertyChanged
{
       int description;
       public int Description
        {
            get { return description; }
            set
            {
                description = value;
                RaiseNotifyPropertyChanged("Description");
            }
        }
        .....
}

public class CalculatorViewModel
{
       public int Description    { get; set; }
}

Let me repeat myself and explain a little more. The whole purpose of the ViewModel is to be bound to the View. Public setters in this class are needed for the sole purpose of accepting changes from the View (public getters are not). Those changes are done by the controls. You don't need to notify the View again on changes it just made.

In other words, a lot of properties in the ViewModel can be perfectly fine if implemented by automatic properties.

Only properties that affect calculations should notify the UI. And not about their own changes. They should notify the UI that the results of the calculated properties have changed. So should the methods. If we have a method Load and it changes the values of all properties by loading them from a database - here is the perfect moment to notify the UI that those properties were changed. Not in the property setter itself.

Having understood all this, we could write our ViewModel in this way:

C#
public class ProductViewModel : INotifyPorpertyChanged
{
       public string Name { get; set; }
       public string Description { get; set; }
       public DateTime Expired { get; set; }

    decimal price;
    public decimal Price
    {
        get { return price; }
        set 
        { 
            if (value != price) 
            {
                price = value;
                NotifyUI("Tax");
                NotifyUI("Total");
            }
        }
    }

    public decimal Tax { get { return 0.07m * price; } }
    public decimal Total { get { return price + tax; } }

    public void Clear() // public verb, command
    {
    Name = ""; NotifyUI("Name");
    Description = ""; NotifyUI("Desription");
    Expired = DateTime.MaxValue; NotifyUI("Expired");
        Price = 0.0m; 
    }
}

Note that with a little help of static Reflection, a combination of setting of a new value and raising a notification can be combined in one helper method, which will look something like this: SetAndNotify(() => this.Name, "");. It brings us both improved readability and strongly typed notifications.

Now, if you look at the ViewModel above, its notifications don't look like a clutter anymore, do they? In fact, they look like a very important piece of logic because they report to the UI exactly what has been changed and when it changed.

But not only that.

  • They tell us exactly when the UI should be updated.
  • They tell us exactly what property should be updated.
  • They show us dependencies that exist between properties.
  • They hint to us what to test, not just all setters and getters (we should test price set and Load only; and not only values, but also notifications that have been raised).

Each piece of ViewModel now becomes clear and takes the correct place. And, by the way, this clarity is what we lose in any automatic implementation, because an automatic implementation must follow some implicit rules instead. Which is usually - notify the View anyway. In a sense, by automation, we just cover up the initial approach of notifications of the property change in its own setters.

There is still a question on ICommand vs. methods, and as I wrote above, I would prefer to not use Commands at all. But for now, it’s perfectly fine to use Commands, they are way less clutter than raising PropertyChanged on each and every setter.

C#
public class ProductViewModel : INotifyPorpertyChanged
{
    public ICommand ClearCommad { get; private set; }
    public ProductViewModel()
    {
       ClearCommand = new SomeSortOfDelegateCommand(() => Clear());
    } 
    ...
}

And here is where I want to finish.

Conclusion

Probably the last part is a little controversial at the moment. Or might seem insignificant. And it is indeed a really small one. I named this technique "Clean INPC", but on the other hand, it may be too much to name it at all.

It is not a framework. It is not even a helper class. It's just a suggestion to write ViewModel in a little different way.

But this method, in my opinion, reflects the very nature and purpose of MVVM, and it does that explicitly and clearly. In the end, it creates better, cleaner ViewModel.

But, if you still hate to implement INotifyPropertyChanged, try the "Dynamic INPC" example. The ability to use Reflection through dynamic in C# 4.0 is really cool.

Thank you very much.

History

  • 03/26/2011: First draft.
  • 03/27/2011: Adding the project to illustrate an update of 100 properties.

License

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


Written By
Software Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralI remember this sort of thing a while back, nice idea I think Pin
Sacha Barber28-Mar-11 11:26
Sacha Barber28-Mar-11 11:26 
GeneralRe: I remember this sort of thing a while back, nice idea I think [modified] Pin
Oleg Kudinov28-Mar-11 11:43
Oleg Kudinov28-Mar-11 11:43 
GeneralRe: I remember this sort of thing a while back, nice idea I think Pin
Sacha Barber28-Mar-11 21:48
Sacha Barber28-Mar-11 21:48 
GeneralRe: I remember this sort of thing a while back, nice idea I think Pin
Yury Goltsman5-Apr-11 3:43
Yury Goltsman5-Apr-11 3:43 
GeneralRe: I remember this sort of thing a while back, nice idea I think Pin
Oleg Kudinov5-Apr-11 5:58
Oleg Kudinov5-Apr-11 5:58 

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.