When is CanExecute called?

前端 未结 4 1995
离开以前
离开以前 2020-11-29 10:41

In the demo, I have a button to toggle a bool field isAsking. I create a command which can execute only when isAsking==true.

Once I press T

相关标签:
4条回答
  • 2020-11-29 11:19

    To expand a comment by Default

    Suppose we have the following

    public class SomeClass : ViewModelBase {
       public ICommand ConnectButtonCommand { get; }
       public SomeClass(){
          //...
          ConnectButtonCommand = new DelegateCommand(ConnectButton_Click, ConnectButton_CanExecute);
          //...
       }
       public DoSomething(){
          //do something that affects the result of ConnectButton_CanExecute
          ((DelegateCommand)ConnectButtonCommand).RaiseCanExecuteChanged();
       }
       private void ConnectButton_Click() {/*...*/}
       private bool ConnectButton_CanExecute() {/*...*/}
    }
    

    I am working on a UWP app that uses Prism for MVVM. Universal windows platform is very similar to WPF.

    0 讨论(0)
  • 2020-11-29 11:21

    I try to search for "the CommandManager detects conditions" and reach this exellent article.

    By examining .NET Framework source code, the author finds that the CommandManager doesn't detect conditions by itself, rather than when Keyboard.KeyUpEvent, Mouse.MouseUpEvent, Keyboard.GotKeyboardFocusEvent, or Keyboard.LostKeyboardFocusEvent occurs, it will reevaluate CanExecute method.

    The article includes other information, but the above part has been enough for me.

    0 讨论(0)
  • 2020-11-29 11:46

    The technical answer is that CanExecute will be invoked whenever the CommandManager.RequerySuggested event is raised. According to the documentation, this will be...

    ...when the CommandManager detects conditions that might change the ability of a command to execute.

    In practical terms, this just means that you don't need to worry about when CanExecute is called: WPF will invoke it when it thinks it is appropriate, and in my experience this will almost always cover your requirements.

    The exception to this is if you have a background task that will cause CanExecute to change it's return value based on something that is not triggered by the UI. In this scenario, you may need to manually force the WPF runtime to re-query CanExecute which you can do by calling CommandManager.InvalidateRequerySuggested

    0 讨论(0)
  • 2020-11-29 11:46

    RoutedCommand contains an event CanExecuteChanged which internally hook to the CommandManager.RequerySuggested event -

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

    And CommandManager.RequerySuggested event is raised

    whenever changes to the command source are detected by the command manager which is in your case is Window. So, when button is clicked, commandManager raised the RequerySuggested event and hence executed the CanExecute predicate registered for your command.

    Also, CommandManager has a static method - InvalidateRequerySuggested which forces the CommandManager to raise the RequerySuggestedEvent. So, you can call that to validate your commands too manually.

    0 讨论(0)
提交回复
热议问题