簡體   English   中英

什么時候調用 CanExecute?

[英]When is CanExecute called?

在演示中,我有一個按鈕來切換 bool 字段isAsking 我創建了一個只能在isAsking==true時執行的命令。

一旦我按下 Toggle 按鈕, okButton.IsEnable立即更改,這表明命令找到了isAsking的更改。

我很困惑為什么命令對象會注意到字段的變化。 什么CanExecute會調用CanExecute

盡管編寫 WPF 應用程序已有一段時間,但我還是 WPF 命令的新手。 請對此案例進行解釋,如果可能,請指出一些相關的文章或博客(我已經閱讀了太多關於剪切/粘貼命令的文章)。

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        x:Class="WpfApplication1.MainWindow"
        Title="MainWindow" Height="350" Width="525" x:Name="mainWindow" >
    <StackPanel>
        <Button Name="okButton" Content="Ok" />
        <Button Content="Toggle"  Click="Button_Click_1"/>
    </StackPanel>
</Window>

代碼隱藏:

public partial class MainWindow : Window
{
    private bool isAsking;

    public MainWindow()
    {
        InitializeComponent();

        CommandBinding cb = new CommandBinding();
        cb.Command = okCommand;
        cb.CanExecute += CanOKExecute;
        cb.Executed += cb_Executed;
        mainWindow.CommandBindings.Add(cb);
        okButton.Command = okCommand;
    }

    private RoutedCommand okCommand = new RoutedCommand("ok", typeof(MainWindow));


    void cb_Executed(object sender, ExecutedRoutedEventArgs e)
    {
       
    }

    void CanOKExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = isAsking;
    }

    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        isAsking = !isAsking;
    }
}

技術上的答案是,只要引發CommandManager.RequerySuggested事件,就會調用CanExecute 根據文檔,這將是...

...當 CommandManager 檢測到可能改變命令執行能力的條件時。

實際上,這只是意味着您無需擔心何時調用CanExecute :WPF 會在它認為合適時調用它,根據我的經驗,這幾乎總能滿足您的要求。

例外情況是,如果您有一個后台任務會導致CanExecute根據 UI 未觸發的內容更改其返回值。 在這種情況下,您可能需要手動強制 WPF 運行時重新查詢CanExecute ,您可以通過調用CommandManager.InvalidateRequerySuggested來執行此操作

我嘗試搜索“CommandManager 檢測條件”並找到這篇優秀的文章

通過查看 .NET Framework 源代碼,作者發現CommandManager本身並沒有檢測條件,而是在發生Keyboard.KeyUpEventMouse.MouseUpEventKeyboard.GotKeyboardFocusEventKeyboard.LostKeyboardFocusEvent時,它會重新評估 CanExecute 方法。

這篇文章包括其他信息,但以上部分對我來說已經足夠了。

RoutedCommand包含一個事件CanExecuteChanged ,它在內部掛鈎到CommandManager.RequerySuggested事件 -

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

並引發CommandManager.RequerySuggested事件

每當命令管理器檢測到命令源的更改時,在您的情況下是 Window。 因此,當單擊按鈕時,commandManager 會引發 RequerySuggested 事件並因此執行為您的命令注冊的 CanExecute 謂詞。

此外,CommandManager 有一個靜態方法 - InvalidateRequerySuggested ,它強制 CommandManager 引發 RequerySuggestedEvent。 因此,您也可以調用它來手動驗證您的命令。

默認展開評論

假設我們有以下

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() {/*...*/}
}

我正在開發一個將 Prism 用於 MVVM 的 UWP 應用程序。 通用 windows 平台與 WPF 非常相似。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM