Are there any performance implications with CanExecuteCommand?
Asked Answered
P

2

7

What are the performance implications of using the CanExecuteCommand of the ICommand object. Is the method executed over and over again?

I need to iterate through a collection of about 200 objects based on which its decided whether the button bound to the Command should be enabled? Does the CanExecuteCommand get executed repeatedly which will make my application slow

Pulse answered 7/9, 2011 at 14:33 Comment(4)
Yes, but only if you're not prematurely optimizing.Gladdie
Will your comment is a bit ambiguous.Heroworship
Will, I also dont completely understand. My validation is an iteration of about 200 objects - a tree view. It just checks a simple property and not very time consuming when run one time. My concern is if the CanExecute is fired repeatedly making the code slow. Can someone please throw some lightPulse
Will is saying the following: Your code in CanExecute should not be doing too much, because this can really be called often. But you shouldn't only worry about this, if this REALLY makes your program slow, i.e. if you can measure a degradation of performance because of too many calls to CanExecute.Pickett
C
15

The ICommand interface is the following:

public interface ICommand
{
    // two methods
    bool CanExecute(object parameter);
    void Execute(object parameter);

    // one event
    event EventHandler CanExecuteChanged;
}

The CanExecuteChanged event should be raised any time you want to indicate that the CanExecute method should be checked/called by WPF. Whoever implements ICommand should raise the event and whoever needs to refresh the button enabled state on the GUI (the WPF system) should register for and handle the event and it calls CanExecute.

In Josh Smith's RelayCommand class, he uses WPF's built-in CommandManager class to raise CanExecuteChanged:

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

In essence, WPF's CommandManager is a singleton that listening for all sorts of routed events: KeyUpEvent, MouseUpEvent, etc... and then tells everyone "hey something interesting happened" by raising its RequerySuggested event. So if you are using RelayCommand, your CanExecute will get called every time CommandManager thinks something interesting happened on the GUI (even if it has nothing to do with your collection). If you have 50 commands, each time you key up, it's rechecking all 50 commands. So yes, this could be a performance issue. However, if your logic in your CanExecute method is really simple, it's probably a non issue. Takeaway point: don't make database or network API calls in the CanExecute method.

The alternative to piggybacking off CommandManager.RequerySuggested to raise the ICommand.CanExecuteChanged event is to roll-your-own version of RelayCommand where you do your own checking and raise CanExecuteChanged manually, or look at the Prism framework's DelegateCommand class, where they do not tie into CommandManager and you have to manually raise the CanExecuteChanged event, which you could probably do by creating a listener for PropertyChanged and then raising CanExecuteChanged on the command.

I agree with @Will above though. RelayCommand will probably work over 80% of the time without issues. If you do start finding performance issues, then you can create your own version of RelayCommand or use the Prism DelegateCommand and raise CanExecuteChanged manually.

Clamorous answered 7/9, 2011 at 15:28 Comment(2)
Related answer here: #6635277Clamorous
Thanks Kendrick and Will, your answers summed it for me. I will put it in CanExecute and look for any performance lag. If I find one, then will look at other implementationsPulse
B
0

For future googlers: I have created a somewhat different command implementation. For one, it is bound to the OnPropertyChanged event of the ViewModelBase class, but it also allows the View Model to Raise the CanExecuteChanged event for all Command instances within it, regardless of a change in property, such as in the case of a One Way To Source binding scenario. this solution is a part of the PerrypheralFrameowrk.WPF Assembly, available on nuget and codeplex. Look it up. The codeplex wiki has a detailed documentation, and so do the classes in the assembly.

Barrel answered 1/11, 2014 at 21:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.