d.moncada
d.moncada

Reputation: 17402

How to prevent CommandManager from invoking CanExecute whenever there is UI interaction?

Our UI currently has a lot of controls that are bound to commands with some complex CanExecutes. The problem we are facing is that whenever CommandManager determines that the UI needs to be re-evaulated, all commands run their CanExecute, which in turn, causes quite a performance hit for specific scenarios.

Reading this post: How does CommandManager.RequerySuggested work?

It seems that the CommandManager will re-evaulate on simple key down, mouse move events, etc. Is there a way to prevent this from happening, and instead, have the command manager re-evaluate when manually invoked?

Upvotes: 3

Views: 1184

Answers (1)

Benjamin Gale
Benjamin Gale

Reputation: 13177

A solution might be to implement a simpler version of the RelayCommand class that simply stores the event handlers itself and exposes a public method to fire them when appropriate:

public class RelayCommand : ICommand
{
    public event EventHandler CanExecuteChanged;

    // Further ICommand implementation omitted...

    public void Invalidate()
    {
        var handler = this.CanExecuteChanged;
        if (handler != null)
        {
            handler(this, EventArgs.Empty);
        }
    }
}

You then call the following in your viewModel to re-evaluate the command:

fooCommand.Invalidate();

Of course, this leaves you with the opposite problem that you now have to manually re-evaluate all commands...

Edit

To elaborate on the comments, most RelayCommand's implement the CanExecuteChanged event like this:

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

When the UI subscribes to the command's CanExecuteChanged event it is actually being indirectly subscribed to the CommandManager.RequerySuggested event which is why your CanExecute method is being called every time the CommandManager suggest a re-query.

The simpler RelayCommand I have suggested avoids this problem by not subscribing to the CommandManager.RequerySuggested event.

Upvotes: 1

Related Questions