在演示中,我有一个切换bool字段isAsking
的按钮。我创建了一个只能在isAsking==true
时执行的命令。
按下切换按钮后,okButton.IsEnable
立即更改,这表示命令发现isAsking
的更改。
当我调用CanExecute
时,为什么命令对象会注意到字段的更改,我感到非常困惑?
虽然编写WPF应用程序已有一段时间了,但我是WPF Command的新手。请对此案例进行解释,如果可能的话,请指出一些相关文章或博客(我已经阅读过太多关于剪切/粘贴命令的文章)。
<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;
}
}
答案 0 :(得分:31)
技术答案是每当引发CommandManager.RequerySuggested
事件时都会调用CanExecute
。根据文档,这将是......
...当CommandManager检测到可能改变命令执行能力的条件时。
实际上,这只是意味着您不必担心何时调用CanExecute
:WPF会在认为合适的时候调用它,根据我的经验,这几乎总能满足您的要求
例外情况是,如果您有后台任务,将导致CanExecute
根据UI未触发的内容更改其返回值。在这种情况下,您可能需要手动强制WPF运行时重新查询CanExecute
,您可以通过调用CommandManager.InvalidateRequerySuggested
答案 1 :(得分:25)
我尝试搜索“CommandManager检测到条件”并到达this exellent article。
通过检查.NET Framework源代码,作者发现CommandManager
本身并不检测条件,而不是Keyboard.KeyUpEvent
,Mouse.MouseUpEvent
,Keyboard.GotKeyboardFocusEvent
,或Keyboard.LostKeyboardFocusEvent
发生,它将重新评估CanExecute方法。
该文章包含其他信息,但上述部分对我来说已经足够了。
答案 2 :(得分:8)
RoutedCommand
包含一个事件CanExecuteChanged
,它在内部挂钩CommandManager.RequerySuggested
事件 -
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
CommandManager.RequerySuggested
事件被提出
命令检测到命令源的更改 在你的情况下经理是窗口。因此,当单击按钮时,commandManager会引发RequerySuggested事件,从而执行为您的命令注册的CanExecute谓词。
此外,CommandManager有一个静态方法 - InvalidateRequerySuggested
,它强制CommandManager引发RequerySuggestedEvent。因此,您可以调用它来手动验证命令。
答案 3 :(得分:0)
默认情况下扩展comment
假设我们有以下内容
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非常相似。