何时调用CanExecute
本文关键字:CanExecute 调用 何时 | 更新日期: 2023-09-27 17:51:26
在演示中,我有一个按钮来切换bool字段isAsking
。我创建了一个命令,只有当isAsking==true
.
一按Toggle键,okButton.IsEnable
立即发生变化,说明命令找到了isAsking
的变化。
我感到非常困惑,为什么命令对象注意到一个字段的变化。何时调用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框架源代码,作者发现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
事件引发
当命令检测到对命令源的更改时manager,在你的例子中是Window。因此,当单击按钮时,commandManager引发RequerySuggested事件,并因此执行为命令注册的CanExecute谓词。
另外,CommandManager有一个静态方法- InvalidateRequerySuggested
,它强制CommandManager引发requery建议事件。因此,您也可以调用它来手动验证您的命令
默认展开注释
假设我们有以下
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 for MVVM的UWP应用程序。通用windows平台与WPF非常相似