Home > Development > A view model base class to use with MVVM in WPF

A view model base class to use with MVVM in WPF

As I mentioned in previous posts (here, here, and here), when you develop WPF application, you’ll eventually use view models. So, instead of keep developing them from scratch, I’m posting three different alternatives for easy reference.

The simple view model

public class ViewModelBase : INotifyPropertyChanged
{
	#region Implementation of INotifyPropertyChanged

	public event PropertyChangedEventHandler PropertyChanged;

	protected virtual void OnPropertyChanged(string propertyName)
	{
		OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
	}

	protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
	{
		var handler = PropertyChanged;
		if (handler != null)
			handler(this, args);
	}

	#endregion
}

This is the simplest class you can have. It implements the INotifyPropertyChanged interface and provides two protected methods for you to notify that a specific property as changed. On that takes the string as a parameter, and another that takes a PropertyChangedEventArgs object. The problem with this approach is that you’ll keep creating new instances of PropertyChangedEventArgs, even though you have a limited number of properties in the class.

The smarter view model

public abstract class ViewModelBaseWithArgCache : ViewModelBase
{
	private readonly Dictionary<string, PropertyChangedEventArgs> eventArgsCache;

	protected ViewModelBaseWithArgCache()
	{
		eventArgsCache = new Dictionary<string, PropertyChangedEventArgs>();
	}

	#region Overrides

	protected override void OnPropertyChanged(string propertyName)
	{
		PropertyChangedEventArgs args;
		if (!eventArgsCache.ContainsKey(propertyName))
		{
			args = new PropertyChangedEventArgs(propertyName);
			eventArgsCache.Add(propertyName, args);
		}
		else
		{
			args = eventArgsCache[propertyName];
		}

		OnPropertyChanged(args);
	}

	#endregion

}

Here, we’re overriding OnPropertyChanged(string propertyName), to provide a custom implementation. First we initialize a dictionary of , that we’re going to use as cache. Now, whenever we call OnPropertyChanged(string property), we check if we have an instance of EventArgs cached for that property. If we do, we return it. If we don’t, we create it, add it to the cache, and then return it. We use that instance to call the protected OnPropertyChanged(PropertyChangedEventArgs args) of ViewModelBase.

The unified view model

public class UnifiedViewModelBase : INotifyPropertyChanged
{
	private readonly Dictionary<string, PropertyChangedEventArgs> eventArgsCache;

	protected UnifiedViewModelBase()
	{
		eventArgsCache = new Dictionary<string, PropertyChangedEventArgs>();
	}

	#region Implementation of INotifyPropertyChanged

	public event PropertyChangedEventHandler PropertyChanged;

	protected void OnPropertyChanged(string propertyName)
	{
		PropertyChangedEventArgs args;
		if (!eventArgsCache.TryGetValue(propertyName, out args))
		{
			args = new PropertyChangedEventArgs(propertyName);
			eventArgsCache.Add(propertyName, args);
		}

		OnPropertyChanged(args);
	}

	protected void OnPropertyChanged(PropertyChangedEventArgs args)
	{
		var handler = PropertyChanged;
		if (handler != null)
			handler(this, args);
	}

	#endregion
}

Now, instead of have a two-level hierarchy of classes, we combined them together in a single UnifiedViewModelBase. You may want to rename this class to something like ViewModelBase.

You can download all the code in this post by clicking this link.

Hope this helps!

Shout it

kick it on DotNetKicks.com

Categories: Development Tags: , ,
  1. MattF
    July 7th, 2009 at 02:00 | #1

    Or you could just use Dependency Properties. From what i have heard bindings actually perform better(i.e. faster) with Dependency Properties compared to INotifyPropertyChanged because in the latter it needs to use Reflection, which is very slow.

  2. July 7th, 2009 at 02:46 | #2

    @MattF
    Thanks for your feedback.

    It depends what you want to accomplish. While both work, I prefer INotifyPropertyChanged for a couple of reasons: DependencyProperties have thread affinity, and overrides (and seals) Equals and GetHashCode. Also, you cannot serialize them. It’s true that you have a performance hit, but from my experience it’s more theoretical than something you’ll actually notice.

    Check out this post by Kent Boogaart and this question in Stack Overflow.

  3. July 7th, 2009 at 11:52 | #3

    @MattF
    I find the use of DependencyProperties in a ViewModel to be extremely impure. That requires your ViewModel to be a DependencyObject, which means your ViewModel is extremely view-dependent. In addition, it makes testing very difficult in Silverlight (with NUnit, at least). Finally, the use of DependencyProperties makes for extremely ugly code. Are you really concerned with reflection at the UI level? I use INotifyPropertyChanged objects a lot, but I have never noticed a perceived performance hit.

    @Pedro
    Which gets me to a question for you. What benefit do you get from caching PropertyChangedEventArgs? Why not new them up in the base class every time something changes? Did you notice any perceivable performance improvements by doing so?

    Brian

  4. July 7th, 2009 at 14:55 | #4

    @Brian Genisio
    You make a good point about unit testing. That’s indeed one of the reasons not to use DependencyProperties, and a very good one.
    On the “new up” issue, I do that not so much because of the performance improvement, but more related to creating multiple instances of “the same” object. I took the hint from EventArgs.Empty.

  5. Joe Feser
    July 8th, 2009 at 18:37 | #5

    You need to use the TryGetValue method instead of performing two lookups for each property change:

    PropertyChangedEventArgs args;
    if (!eventArgsCache.TryGetValue(propertyName, out args))
    {
    args = new PropertyChangedEventArgs(propertyName);
    eventArgsCache.Add(propertyName, args);
    }

    Joe Feser

  6. July 9th, 2009 at 05:53 | #6

    @Joe Feser
    Thanks, Joe! I’ve updated the post and the source code download with your suggestions.

  7. July 9th, 2009 at 11:22 | #7

    Hi Brian

    I believe you are optimizing at the wrong place. I don’t believe that creating a new EventArg object every time a property changes is a performance issue. These objects are very simple and the garbage collector doesn’t have any problems to collect them.

    Another story is the “string” property name you have to use. When you need to refactor a property name then the risk is high that this “string” isn’t updated. Such a bug is often hard to find because it might affect just one UI field that doesn’t update itself.

    A solution to this issue is shown here:

    WPF Application Framework (WAF)
    http://waf.codeplex.com

  8. Daniel
    July 16th, 2009 at 19:30 | #8

    Sorry to be harsh, but this is absolutely useless micro-optimization. An average desktop today can instantiate tens of millions of new objects a second. You are probably wasting more clock cycles doing dictionary look ups than just instantiate a new one. The worst part is some junior developer will see this and just copy the code.

  9. July 22nd, 2009 at 23:15 | #9

    @Pedro Sampaio
    Hi, Pedro!

    Another one point.

    Using Dictionary is not best choice on small number of properties (<= 9).
    It's better to use SortedList. Otherwise you'll get memory overhead because of Dictionary using Hash table internally.

  1. July 6th, 2009 at 02:29 | #1
  2. July 6th, 2009 at 02:37 | #2
  3. July 6th, 2009 at 15:44 | #3