我在Commands及其CanXXXExecute方面遇到了一些问题......我当时认为这是一个Catel(MVVM框架)问题,但我已经用标准的WPF应用程序测试了自己,但它仍然会发生..
在我发布的示例中,我已经在加载时调用了2次“CanClickCommandExecute”方法(一个在构造函数中,我同意这一点,另一个我认为在视图中加载)和3次单击时按钮!!
这是XAML
<Window x:Class="StandardWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Command="{Binding ClickCommand}" Content="ClickMe!" Background="Teal"></Button>
</Grid>
.cs
public partial class MainWindow : Window
{
public ICommand ClickCommand { get; private set; }
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
ClickCommand = new RelayCommand(OnClickCommandExecute,CanClickCommandExecute);
}
private bool CanClickCommandExecute()
{
Debug.WriteLine("Standard OnClickCommandExecute fired!");
return true;
}
private void OnClickCommandExecute()
{
//something weird in there!
}
}
RelayCommand(取自here)
public class RelayCommand : ICommand
{
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
private Action methodToExecute;
private Func<bool> canExecuteEvaluator;
public RelayCommand(Action methodToExecute, Func<bool> canExecuteEvaluator)
{
this.methodToExecute = methodToExecute;
this.canExecuteEvaluator = canExecuteEvaluator;
}
public RelayCommand(Action methodToExecute)
: this(methodToExecute, null)
{
}
public bool CanExecute(object parameter)
{
if (this.canExecuteEvaluator == null)
{
return true;
}
else
{
bool result = this.canExecuteEvaluator.Invoke();
return result;
}
}
public void Execute(object parameter)
{
this.methodToExecute.Invoke();
}
}
为什么会这样?我怎样才能发现正在发生的事情?在我的实际案例中,我使用CanXXX来执行验证...在这种情况下,我得到了很多次验证并且在一些对象上可能需要花费很多时间
答案 0 :(得分:4)
为什么CanxxxCommandExecute被解雇了很多次?
因为您多次提升CanExecuteChanged
方法,所以CanExecute
会被wpf多次评估。
您不是自己直接提出活动,但是CommandManager.RequerySuggested会这样做。
正如文档所述当CommandManager检测到可能改变命令执行能力的条件时发生。 CommandManager.RequerySuggested
将猜测可能需要更新按钮的事件&#39 ; s州。它可能会发生很多次,例如最小化应用程序会触发它;等
如果要控制何时调用CanExecute
,请手动引发事件。请勿使用CommandManager.RequerySuggested
。
答案 1 :(得分:1)
如果查看.NET Framework源代码,CommandManager本身并不检测条件,而是当Keyboard.KeyUpEvent,Mouse.MouseUpEvent,Keyboard.GotKeyboardFocusEvent或Keyboard.LostKeyboardFocusEvent发生时,它将触发CanExecute方法;显然,这可能会发生多次。