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.