强制重新评估ICommand.CanExecute

本文关键字:评估 ICommand CanExecute 新评估 | 更新日期: 2023-09-27 18:21:25

在WPF XAML中,我有一个ButtonCommand属性,用于实现ICommand的类的实现。

在这个实现中,我没有将我的CanExecuteChanged事件连接到使用CommandManager.RequerySuggested上——我想控制何时调用CanExecute,并且使用它会比必要时更频繁地调用它。

我可以让ICommand.CanExecute重新评估的唯一其他方法是使用类似的东西

public void InvokeCanExecute()
{
    CanExecuteChanged.Invoke(this, new EventArgs());
}

在我的课堂上实现ICommand

这看起来真的很糟糕——我是不是错过了一些显而易见的东西?我尝试过使用PropertyChanged调用重新评估,但似乎不起作用。

强制重新评估ICommand.CanExecute

确实,如果您不想使用CommandManager.RequerySuggested,它确实可能会比必要时更频繁地调用CanExecute,那么您需要显式调用自己的InvokeCanExecute方法,以强制命令重新评估其CanExecute条件。

但是,在大多数情况下,CanExecute条件将取决于公共(可绑定)属性,即引发PropertyChanged事件以指示其值已更改的属性-可以挂接到此事件,以便在命令所依赖的属性之一发生更改时自动调用InvokeCanExecute。关于如何实现这样一个命令的示例,请参阅这家伙的博客文章(如果我没有错的话,这种方法是作为MVVM Light工具包的一部分实现的)。

使用这种方法实例化命令看起来有点像以下内容:

SaveCommand = new RelayCommand(() => { /* do some stuff; */ }, 
                               () => !string.IsNullOrEmpty(Name), 
                               this, () => Name);

由于命令的CanExecute条件(检查Name是否为空)取决于Name属性,因此每当Name的内容发生更改时,都需要重新评估它。只需将对Name属性的引用传递给命令的构造函数,只要Name的值发生变化,就会自动调用InvokeCanExecute

理论上,可以更进一步,让命令本身检查它所依赖的属性——如果你对这种方法感兴趣,请查看我的一篇博客文章,但请注意,这篇文章在很大程度上依赖于反思,所以它总是取决于详细的用例,这种方法是否可行。此解决方案的示例实现包含在MVVMbasics框架中(免责声明:由我发布)。在这种情况下,您可以将命令初始化代码简化为:

SaveCommand = CreateRelayCommand(() => { /* do some stuff; */ }, 
                                () => !string.IsNullOrEmpty(Name));

不,您并没有真正遗漏任何东西。这里有一个类似的问题,建议您采用相同的方法:CanExecuteChanged和CommandManager.RequeySuggested的实际任务是什么?。

不过,你可以让你的方法更健壮一点:

public void InvokeCanExecute()
{
    var handler = CanExecuteChanged;
    if (handler != null)
    {
        handler(this, new EventArgs());
    }
}