为什么CanxxxCommandExecute被解雇了这么多次?

时间:2015-09-11 12:55:52

标签: c# wpf xaml mvvm catel

我在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来执行验证...在这种情况下,我得到了很多次验证并且在一些对象上可能需要花费很多时间

2 个答案:

答案 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方法;显然,这可能会发生多次。