Search code examples
wpfperformancecommandcanexecute

Performance penalty of continuous CanExecute calls in Command


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.


Solution

  • 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.