Question

I need to refresh the CanExecute state of one or more (though by far not all) RoutedCommand objects.

I know that you can update all commands by using

CommandManager.InvalidateRequerySuggested();

Since this updates far more commands than necessary, calling this function is sometimes a performance problem in my application.

My initial hope was that calling CanExecute() manually would also raise the event if the state changed, but this is not the case.

When looking at the reference source then, the CanExecuteChanged does not seem to be accessible for derived classes to provide some kind of extension to the RoutedCommand class that allows raising the event manually.

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

Any ideas how I could implement such a mechanism? I know about DelegateCommand, but I need a routed command, so I don't think this class can help me.

Was it helpful?

Solution

You can create your own custom RoutedCommand, reimplement ICommand and register an additional event yourself. Note that using new is supposedly safe here because WPF will use an ICommand reference to call CanExecuteChanged.

public class MyRoutedCommand : RoutedCommand, ICommand
{
    private event EventHandler _canExecuteChanged;

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

    public new event EventHandler CanExecuteChanged
    {
        add
        {
            _canExecuteChanged += value;
            base.CanExecuteChanged += value;
        }
        remove
        {
            _canExecuteChanged -= value;
            base.CanExecuteChanged -= value;
        }
    }
}

You should be aware that while WPF will use a WeakEventManager to register to this event, others devs might not. Since routed commands are usually defined as static fields, this could be a potential memory leak. You could implement a weak event manager to prevent this.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top