Weak references & the Prism DelegateCommand

I’ve recently been getting to know WPF rather better than I’d like.

We make a lot of use of the Prism DelegateCommand. One such command had a handler attached to it’s CanExecuteChanged event:

var command = new DelegateCommand(Execute, CanExecute);
command.CanExecuteChanged += OnCommandCanExecuteChanged;

When we asked the command to re-evaluate whether it could execute:

command.RaiseCanExecuteChanged();

Then OnCommandCanExecuteChanged should have been called.

Sometimes it was, sometimes it wasn’t. Or, more accurately, it was at first and then later it wasn’t.

A bit of digging into the sauce of the DelegateCommand (thanks R#!), confirmed the suspicion:

    public event EventHandler CanExecuteChanged
    {
      add
      {
        WeakEventHandlerManager.AddWeakReferenceHandler(ref this._canExecuteChangedHandlers, value, 2);
      }
      remove
      {
        WeakEventHandlerManager.RemoveWeakReferenceHandler(this._canExecuteChangedHandlers, value);
      }
    }

The command holds a weak reference to the event handler. And, if that’s the only reference, then it’s just a matter of time before it gets GCed; and your handler will no longer be called.

After some hair pulling, and a few false starts, it turned out the solution was to keep our own reference to the actual event handler. Makes perfect sense now, but it certainly wasn’t obvious at first!

public class CommandHolder
{
    private readonly EventHandler eventHandler;

    public ICommand Command { get; private set; }

    public CommandHolder()
    {
        Command = new DelegateCommand(Execute, CanExecute);
        eventHandler = OnCanExecuteChanged;
        Command.CanExecuteChanged += eventHandler;
    }

    private void Execute() { }

    private bool CanExecute() { return true; }

    private void OnCanExecuteChanged(object sender, EventArgs e) { }
}

I assume the reason for the weak references is to try & avoid memory leaks caused by failing to unbind event handlers. Unfortunately, it can leave you with a tricky bug to investigate.

3 thoughts on “Weak references & the Prism DelegateCommand

  1. Martin June 12, 2013 / 9:26 am

    Simplest explanation of this problem and its solution (I encountered it quite often during unit testing). Thank you!

    • Rob G June 28, 2013 / 9:46 am

      To clarify, the pattern used here is an alternative solution to the Weak Event Pattern. It may have been better to use the Weak Event Pattern, as its part of WPF itself and documented properly.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s