[英]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.KeyUpEvent
、 Mouse.MouseUpEvent
、 Keyboard.GotKeyboardFocusEvent
或Keyboard.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.