Allowing CommandManager to query your ICommand objects

June 17, 2008

One of the great parts about commands in WPF is that they know if they can currently execute or not. When they cannot execute, the control(s) that are set to execute the command will be disabled automatically. For example, if your application has no changed data, the Save toolbar button will automatically be disabled, assuming its Command property is set to the Save command.

WPF will automatically ask all of the commands being used in your UI if they can execute. This happens at various times, such as when input focus shifts to another control, an item is selected in a list, etc. You can also programmatically trigger this to happen by calling the CommandManager’s InvalidateRequerySuggested static method. This all seems magical, dreamy, and almost too good to be true.

Here’s the hitch: this beautiful system of commands automatically notifying the UI that they cannot execute only works out-of-the-box for RoutedCommands. If you simply implement ICommand and hook up, say, a Button’s Command property to reference that non-routed command, suddenly the Magical Love Machine comes to a grinding and screeching halt. Why? Because by default WPF has no idea that your custom ICommand objects exist. How would it?

Fortunately there is an easy solution to this problem. In your ICommand implementation, you make the CanExecuteChanged event hook the CommandManager’s RequerySuggested event. I lifted this little trick straight from Reflector, as I perused the RoutedCommand class…

class MyCommand : ICommand
{
public bool CanExecute(object parameter)
{
return maybeTrueOrFalse;
}

public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}

public void Execute(object parameter)
{
// Do something awesome.
}
}