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
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.
The
ICommand
interface is the following:The
CanExecuteChanged
event should be raised any time you want to indicate that theCanExecute
method should be checked/called by WPF. Whoever implementsICommand
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 callsCanExecute
.In Josh Smith's
RelayCommand
class, he uses WPF's built-inCommandManager
class to raiseCanExecuteChanged
: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 itsRequerySuggested
event. So if you are usingRelayCommand
, yourCanExecute
will get called every timeCommandManager
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 yourCanExecute
method is really simple, it's probably a non issue. Takeaway point: don't make database or network API calls in theCanExecute
method.The alternative to piggybacking off
CommandManager.RequerySuggested
to raise theICommand.CanExecuteChanged
event is to roll-your-own version ofRelayCommand
where you do your own checking and raiseCanExecuteChanged
manually, or look at the Prism framework'sDelegateCommand
class, where they do not tie intoCommandManager
and you have to manually raise theCanExecuteChanged
event, which you could probably do by creating a listener forPropertyChanged
and then raisingCanExecuteChanged
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 PrismDelegateCommand
and raiseCanExecuteChanged
manually.