Unit testing ICommand.CanExecute when using CommandManager

359 Views Asked by At

(Part of) my ICommand implementation is:

    public void RaiseCanExecuteChanged()
    {
        CommandManager.InvalidateRequerySuggested();
    }

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

This works fine in the UI when calling RaiseCanExecuteChanged(), but in a unit test I want to know if the UI has been notified that it should call the CanExecute method. Subscribing to the CanExecuteChanged event doesn't work because this event is not triggered as the CommandManager is used instead. Does anyone know how to test if CommandManager.InvalidateRequerySuggested has been triggered?

I am also considering not using the CommandManager and changing my implementation to:

    public void RaiseCanExecuteChanged()
    {
        CanExecuteChanged?.Invoke(this, EventArgs.Empty);
    }

    public event EventHandler CanExecuteChanged;

the advantage seems to be that this only triggers calling the CanExecute for a specific command, rather than for all commands registered with the CommandManager. Can someone confirm that my understanding about the CommandManager is correct? Does anyone know disadvantages for this approach with a "normal" CanExecuteChanged event?

1

There are 1 best solutions below

0
On

Personally I prefer to use an ICommand implementation that requires explicitly calling CanExecuteChanged - I use MVVM Light RelayCommand. When you rely on the CommandManager, you never know when CanExecuteChanged will be called - possibly after every key stroke or mouse click which can get very inefficient.

For my own take on WPF commands, especially creating automated CanExecuteChanged dependencies on other properties, take a look at my recent blog post.