21

Can I use CanExecuteChanged to change the "can execute" condition?

Or else... "for what" its used?

Tim Lloyd
  • 37,954
  • 10
  • 100
  • 130
Relativity
  • 6,690
  • 22
  • 78
  • 128

3 Answers3

27

No you can not use it to change the can execute state. It is an event and objects which participate in the ICommand pattern can choose to listen to this event e.g. a button may use this event to know when to re-query the commands state (by calling the can execute method) to set its enabled state.

In order for the can execute pattern to be useful there needs to be something that can be used to raise the event. Prism's DelegateCommand has a method you can call to manually raise this event so subscribers will re-query the can execute method if they have opted into the pattern.

  • Assign command to button.
  • Button subscribes to can execute changed event.
  • Button execute can execute method and it returns false - disables button.
  • You change state that can execute method depends on.
  • You call raise can execute changed on Prism command.
  • Can execute changed event is raised.
  • Button event handler fires.
  • Button calls command can execute method - button is enabled.

Example

In the following Prism based example we change the state of SaveCommand CanExecute from false to true whilst the save command is executing. The call toRaiseCanExecuteChanged will cause the CanExecuteChanged event to be raised, and clients to call the CanExecute method. In practice this would make a Save button that was bound to SaveCommand change its state from enabled to disabled and back to enabled again.

public class BlingViewModel
{
    private DelegateCommand<object> _saveCommand;
    private bool _canSaveExecute = true;

    public ICommand SaveCommand
    {
        get
        {
            if (_saveCommand == null)
            {
                _saveCommand = new DelegateCommand<object>
                    (
                    executeMethod: _ => Save()
                    ,
                    canExecuteMethod: _ => _canSaveExecute
                    );
            }
            return _saveCommand;
        }
    }

    private void Save()
    {
        _canSaveExecute = false;
        _saveCommand.RaiseCanExecuteChanged();

        Console.WriteLine("Saving...");

        _canSaveExecute = true;
        _saveCommand.RaiseCanExecuteChanged();
    }
}
Noctis
  • 11,507
  • 3
  • 43
  • 82
Tim Lloyd
  • 37,954
  • 10
  • 100
  • 130
  • IS there anyway that I can redefine my CanExecute Conditions dynamically ? – Relativity Dec 25 '10 at 19:36
  • @Anish Yes the idea is for your CanExecute method to refer to some state (e.g. a bool). You can change this at will, but after your change you must call your framework's method of raising the can execute changed event e.g. RaiseCanExecuteChanged for Prism command. All elements that listening to the event will then call the CanExecute method and proceed with the value that is returned. – Tim Lloyd Dec 25 '10 at 19:46
  • "You can change this at will," => How can I change it...I need to edit not a new one. – Relativity Dec 25 '10 at 20:57
  • @Anish you cannot change the can execute method, but you can change the variables which it refers to. I'll try and give you a code sample but I'm on my phone - it's painful! – Tim Lloyd Dec 25 '10 at 21:08
9

Or just call System.Windows.Input.CommandManager.InvalidateRequerySuggested() so that your CanExecute handlers are re-evaluated.

Jodrell
  • 34,946
  • 5
  • 87
  • 124
  • Good point, thank you. Do you know if this approach has a performance hit (tangible impact, e.g. medium/heavy usage of commands within UI)? – Luke Feb 15 '12 at 09:23
  • Its not somthing I've had a problem with, I imagine that depends on the number and complexity of the handlers and the performance of the system in general. – Jodrell Feb 15 '12 at 09:37
2
public override event EventHandler CanExecuteChanged
{    
    add { CommandManager.RequerySuggested += value; }
    remove { CommandManager.RequerySuggested -= value; }
}

I don't know what the performance implications are for this; however, they don't seem to be too great, either way. This is what I use.

Thomas
  • 6,291
  • 6
  • 40
  • 69