Pages

Friday, 25 June 2010

Morgan Skinner, an Application Development Consultant with Microsoft UK, had a post on his blog yesterday complaining at the quantity of boilerplate code needed to create commands in ViewModels for WPF and Silverlight. I share his irk about that.

He shows a clever technique involving ICustomTypeDescriptor that avoids creating properties (and hence backing fields) for each of the commands. But I think he goes too far. Without the properties on the ViewModel, its tests are going to have a hard time knowing what commands it exposes; and accessing them through code isn’t going to be as straightforward as a property access.

As you can see, ViewModelBase is providing a Commands property to manage all the commands. This neatly avoids having to create a field for each one. Commands is an instance of CommandHolder which is equally simple:

Since the lifetime of the CommandHolder is bound to the ViewModel (through its base class), I don't see that there will be any lifetime issues caused by the delegates. If the CommandHolder instance was static, that would be a different matter.

@Scott That is an awesome refactoring. I've put the Commands property on my base ViewModel, and now the amount of code in the concrete ViewModels is even smaller, and everything is refactoring-friendly.

@Scott That is an awesome refactoring. I've put the Commands property on my base ViewModel, and now the amount of code in the concrete ViewModels is even smaller, and everything is refactoring-friendly.

This use of CanExecute in this implementation did not work for me, in cases where the CanExecute trigger was a changeable property within the same WPF window.

I was able to get it working by replacing:public event EventHandler CanExecuteChanged;protected void InvokeCanExecuteChanged(){ EventHandler handler = CanExecuteChanged; if (handler != null) handler(this, EventArgs.Empty);}

License and Disclaimer

In practice, this means that you can take any code you find here and freely use it in your own projects, commercial or otherwise. The only requirement is that you include an attribution link in your source code back to this blog.

The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.