If someone asked you, what are the building blocks of MVVM, what would you say? Models, Views, and ViewModels, of course. It’s in the name. But really, there are two others:

  • Models
  • Views
  • ViewModels
  • Commands
  • Events

If Commands and Events aren’t strongly represented in your application, I’d say there is a strong chance it isn’t factored very well.

One problem I see quite often is the Fat ViewModel: a long, bloated class that violates SRP by presenting complex application Commands to the view, and implementing them too.

Symptoms

You can tell you have a Fat ViewModel if any of the following are true:

  • Instead of having a separate class for each Command, your ViewModel uses DelegateCommands (aka RelayCommands) to invoke methods on itself.
  • Your ViewModel has three properties, two commands, and is 300 lines long.
  • Your ViewModel has a large number of services injected into it.
  • Your ViewModel tests include assertions for both presentation and application behaviour.
  • Testing simple UI behaviour — e.g. a button should be disabled after it has been clicked — requires excessive mocking of dependencies.
  • Your ViewModel tests frequently call xyzCommand.Execute().
  • Commands cannot easily be re-used by other ViewModels. Your application is not modular.
  • ViewModels update their state directly, instead of listening for global application Events.

Instead, if you extract Commands into separate classes, that publish their results via Events, you will benefit by having:

  • Skinny and light ViewModels.
  • Commands that can be developed and tested in isolation.
  • Commands that encapsulate and mask complex logic.
  • Separation of presentation logic (ViewModels) from application logic (Commands).
  • A catalog of clearly defined and reusable Commands that be composed into new ViewModels.

Whither DelegateCommand?

From the cases I have seen, I have no doubt that DelegateCommands are the primary cause of Fat ViewModels — they encourage developers to implement Commands using local ViewModel methods, which results in poorly-factored code. For this reason, I consider DelegateCommands to be in the same bad code smell category as ServiceLocator: as an anti-pattern, with few legitimate uses. (One is when the Command is entirely self-contained within the ViewModel (i.e. does not collaborate with any other object), the other when genuinely delegating to another object. But in that case, the other object should probably be a Command anyway.)

See also: Fat Controller, God Object.

December 8th, 2010 | 7 Comments

Prism’s event aggregator is great for decoupling UI state changes when UI events occur, but sometimes you need to perform some larger, long-running task on a background thread — uploading a file, for example.

Here’s a quick example of an encapsulated event handler listening off the Prism event bus, and using Windsor’s IStartable facility to handle event subscription:

public class TradeCancelledEventHandler : ICompositePresentationEventHandler, IStartable
{
    private readonly IEventAggregator eventAggregator;

    protected TradeCancelledEventHandler(IEventAggregator eventAggregator)
    {
        if (eventAggregator == null)
            throw new ArgumentNullException("eventAggregator");

        this.eventAggregator = eventAggregator;
    }

    public void Start()
    {
        // Register to receive events on the background thread
        eventAggregator
            .GetEvent<TradeCancelledEvent>()
            .Subscribe(Handle, ThreadOption.BackgroundThread);
    }

    public void Stop()
    {
        eventAggregator
            .GetEvent<TradeCancelledEvent>()
            .Unsubscribe(Handle);
    }

    void Handle(TradeCancelledEventArgs eventArgs)
    {
        // ... do stuff with the event
    }
}

Each event handler is effectively a little service running in the container. Note ICompositePresentationEventHandler is a simple role interface that allows us to register them all at once in the IoC container:

public interface ICompositePresentationEventHandler {}

...

container.AddFacility<StartableFacility>();

// Register event handlers in container
container.Register(
    AllTypes
        .Of<ICompositePresentationEventHandler>()
        .FromAssembly(Assembly.GetExecutingAssembly()));
June 24th, 2010 | No Comments Yet

A lot of people have been talking about the Reactive Extensions for .NET, a flash new library from Devlabs which lets you do LINQ to .NET events just like you can with collections. My team at work has started using it pretty heavily, and today I wrote an adapter that allows you to use Rx over events published on the event aggregator in a Prism/Composite WPF application.

Here’s an example of using it in an imaginary chat client, to filter incoming messages from a particular person:

public class ConversationViewModel : IDisposable
{
    public IContact Friend { get; private set; }
    public ObservableCollection<IMessage> Messages { get; private set; }

    public ConversationViewModel(IContact friend,
        IEventAggregator eventAggregator)
    {
        // Interested only in messages sent by the person we are talking to.
        var messageReceivedEvents = eventAggregator
            .GetEvent<MessageReceived>()
            .AsObservable()
            .Where(msg => msg.Sender.Equals(Friend));

        eventSubscription = messageReceivedEvents.Connect();

        messageReceivedEvents.Subscribe(msg => Messages.Add(msg));
    }

    // We will keep receiving messages until the subscription is disposed.
    IDisposable eventSubscription;
}

It was a good exercise that helped me understand a bit more about how Rx works, and illustrates how easy it is to integrate with callback-based event systems (e.g. your favourite message bus).

You can grab the code here: CompositePresentationEventExtensions.cs

Update Jun 16 2010: Added finalizer to CompositePresentationEventSubscription.

March 30th, 2010 | 4 Comments

Last week, I encountered a problem doing some fiddly UI behaviour in a Prism/MVVM app. I wanted something like this:

I wanted a ComboBox where you can choose one of the available options, or none of them. Null, deselected, whatever.

Unfortunately for me, WPF doesn’t support binding null values in ComboBoxes, ListBoxes or ListViews. Now this is a pretty common problem, and a quick google reveals a few solutions available to this problem:

However, if like us, your domain model is all nicely decoupled through interfaces, the easiest way to get null values into a ComboBox is with the null object pattern. (And thankfully for me doesn’t require any knowledge of WPF control internals to implement).

Here’s what my null object looked like:

public class NullCurve : IFxCurve, IEquatable<NullCurve>
{
    public string Name { get { return ""; } }

    public void DoStuff() {} // Has no implementation

    // Note the equality overload. Null objects are value types -- they
    // have no identity, and are all equal.
    public bool Equals(NullCurve other)
    {
        return other != null;
    }

    public override bool Equals(object obj)
    {
        return Equals(obj as NullCurve);
    }

    public override int GetHashCode() { return -1; }
}

To use it, you simply pop a null object at the start of your list. And check whether it was selected on submit:

public class FxCurveSelectionViewModel : ViewModelBase
{
    public ObserableCollection<IFxCurve> AvailableCurves { get; private set; }
    public IFxCurve SelectedCurve { get; set; }

    public FxCurveSelectionViewModel(ICurveRepository curves)
    {
        AvailableCurves = new ObservableCollection<IFxCurve>();
        AvailableCurves.Add(new NullCurve());
        AvailableCurves.AddRange(curves.GetAllCurves());
    }

    public void Submit()
    {
        if (SelectedCurve.Equals(new NullCurve()))
            // nothing was selected
    }
}

XAML binding is standard; no need to change anything because we handle it all in the view model. Which arguably is not the most DRY solution long-term, but sufficient until I learn more about WPF internals to do it elegantly with XAML.

March 27th, 2010 | 6 Comments

Today I am working on my first WPF app, using the WPF Model-View-ViewModel (MVVM) Toolkit. Naturally, we are using TDD — like ASP.NET MVC, WPF ViewModels and ICommands lend themselves very nicely to unit testing, even around difficult dependencies like OpenFileDialog.

Anyway, one problem I am seeing repeated is writing tests for PropertyChanged events firing at the correct time. This is required so that WPF views can display updated values when something changes. For a test helper, I wrote a quick disposable event listener and extension method for this:

[TestMethod]
public void Should_raise_pack_path_property_changed_event()
{
    viewModel.AssertRaisesPropertyChangedFor("PackPath");

    viewModel.OnFileSelected(@"C:\foo.zip");
}

An assertion will fail if the PropertyChanged event does not fire with the correct property name. Here is the extension method:

public static class INotifyPropertyChangedExtensions
{
    public static void AssertRaisesPropertyChangedFor(this INotifyPropertyChanged obj,
        string propertyName)
    {
        new PropertyChangedEventListener(obj, propertyName);
    }
}

… and the event listener:

/// <summary>
/// Helper class for asserting a PropertyChanged event gets raised for a particular
/// property. If it hasn't been called by the time this object is disposed, an
/// assertion will fail.</summary>
public class PropertyChangedEventListener : IDisposable
{
    bool wasRaised = false;
    readonly string expectedPropertyName;
    bool IsDisposed = false;
    readonly INotifyPropertyChanged obj;

    public PropertyChangedEventListener(INotifyPropertyChanged obj, string propertyName)
    {
        if (obj == null)
            throw new ArgumentNullException("obj");

        if (propertyName == null)
            throw new ArgumentNullException("propertyName");

        this.obj = obj;
        this.expectedPropertyName = propertyName;
        obj.PropertyChanged += new PropertyChangedEventHandler(OnPropertyChanged);
    }

    void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (this.expectedPropertyName.Equals(e.PropertyName))
            this.wasRaised = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected void Dispose(bool Disposing)
    {
        if (!IsDisposed)
        {
            if (Disposing)
            {
                // Cleanup references...
                this.obj.PropertyChanged -= new PropertyChangedEventHandler(OnPropertyChanged);

                // Assert we got called
                Assert.IsTrue(this.wasRaised,
                    String.Format("PropertyChanged was not raised for property '{0}'",
                        this.expectedPropertyName));
            }
        }

        IsDisposed = true;
    }

    ~PropertyChangedEventListener()
    {
        Dispose(false);
    }
}

It’s not fancy, and it’s probably not thread-safe, but it does the trick for our app.

May 11th, 2009 | 7 Comments