It's true that - if you don't want to use CommandManager.RequerySuggested
, which indeed might call CanExecute
more often than necessary - you need to explicitly invoke your own InvokeCanExecute
method in order to force the command to re-evaluate its CanExecute
condition.
However, in most cases the CanExecute
condition will depend on public (bindable) properties, meaning properties that raise the PropertyChanged
event to indicate that their value has changed - it is possible to hook into this event, in order to automatically call InvokeCanExecute
whenever one of the properties the command depends on has changed. For an example of how to implement such a command, see this guy's blog post (if I'm not mistaken, this approach is implemented e.g. as part of the MVVM Light toolkit).
Instantiating a command using this approach would look somewhat like the following:
SaveCommand = new RelayCommand(() => { /* do some stuff; */ },
() => !string.IsNullOrEmpty(Name),
this, () => Name);
Since the command's CanExecute
condition (which checks whether Name
is empty) depends on the Name
property, it needs to be re-evaluated whenever Name
's content changes. You simply pass a reference to the Name
property to the command's constructor, and InvokeCanExecute
will automatically be called whenever the value of Name
changes.
In theory, it is possible to go one step further and let the command itself check on which properties it depends - if you're interested in this approach, check out
one of my blog articles, but note that this one heavily depends on reflection so it always depends on the detailed use-case whether this approach is feasible or not. A sample implementation of this solution is included in the MVVMbasics framework (disclaimer: published by me). In this case, you could reduce the command initialization code to:
SaveCommand = CreateRelayCommand(() => { /* do some stuff; */ },
() => !string.IsNullOrEmpty(Name));