4

I am applying the MVVM pattern to a project. I have a UserControl that has a button which is bound to a command exposed by the ViewModel. Since the button is visible, it's calling continuously the CanExecute method of the button. Something tells me that this carries a performance penalty, but I'm not sure. Is this the expected behavior? or is there a better way of having a button bound to a command?

Thank you.

akjoshi
  • 15,374
  • 13
  • 103
  • 121
SoManyGoblins
  • 5,605
  • 8
  • 45
  • 65
  • Why is the button calling `CanExecute` continuously? It doesn't do that by default and should only do so when `ICommand.CanExecuteChanged` has been raised. – Jens Dec 01 '10 at 16:26
  • What type of ICommand are you using? Different implementations can behave a lot differently in regards to CanExecute updates. – John Bowen Dec 01 '10 at 16:26
  • I am just using the regular ICommand interface. Actually the RelayCommand class, which is nothing special except that it uses delegate injection to specify my methods. – SoManyGoblins Dec 01 '10 at 16:35

1 Answers1

1

Sorry, I found out what was happening. This is the implementation of RelayCommand.

public class RelayCommand : ICommand
{
    #region Fields

    readonly Action<object> _execute;
    readonly Predicate<object> _canExecute;

    #endregion // Fields

    #region Constructors

    public RelayCommand(Action<object> execute)
        : this(execute, null)
    {
    }

    public RelayCommand(Action<object> execute, Predicate<object> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");

        _execute = execute;
        _canExecute = canExecute;
    }
    #endregion // Constructors

    #region ICommand Members

    [DebuggerStepThrough]
    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute(parameter);
    }

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

    public void Execute(object parameter)
    {
        _execute(parameter);
    }

    #endregion // ICommand Members
}

I had incorrectly assumed the system was requerying ALL commands automatically. What it actually does is hook to each Command's CanExecuteChanged event, and RelayCommand basically links its CanExecuteChanged event to the CommandManager's RequerySuggested event, so each time the system "suggests" a requery, it was in fact requerying all my RelayCommands.

Thank you.

SoManyGoblins
  • 5,605
  • 8
  • 45
  • 65