简体   繁体   English

强制对ICommand.CanExecute进行重新评估

[英]Forcing Reevaluation on ICommand.CanExecute

In WPF XAML, I've got a Button 's Command property working with an implementation of a class implementing ICommand . 在WPF XAML中,我具有ButtonCommand属性,该属性与实现ICommand的类的实现一起使用。

In this implementation, I don't have my CanExecuteChanged event wired up to use CommandManager.RequerySuggested - I want to have control over when CanExecute is called, and using this calls it way more often than necessary. 在此实现中,我没有连接CanExecuteChanged事件以使用CommandManager.RequerySuggested我想控制何时调用CanExecute,并且使用此调用的次数比必要的多。

The only other way I can get ICommand.CanExecute to re-evaluate is to use something like: 我可以获得ICommand.CanExecute进行重新评估的唯一其他方法是使用类似以下内容的方法:

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

In my class implementing the ICommand . 在我的类中实现ICommand

This seems really nasty - am I missing something obvious? 这看起来真的很讨厌-我是否缺少明显的东西? I've tried invoking the re-evaluation using PropertyChanged but that doesn't seem to work. 我尝试使用PropertyChanged调用重新评估,但这似乎不起作用。

No, you are not really missing anything. 不,您并没有真正错过任何东西。 Here's a similar question that recommends the same approach you're taking: What is the actual task of CanExecuteChanged and CommandManager.RequerySuggested? 这是一个类似的问题,建议您采用相同的方法: CanExecuteChanged和CommandManager.RequerySuggested的实际任务是什么? .

You can make your method a little bit more robust though: 不过,您可以使方法更加健壮:

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

It's true that - if you don't want to use CommandManager.RequerySuggested , which indeed might call CanExecute more often than necessary - you need to explicitly invoke your own InvokeCanExecute method in order to force the command to re-evaluate its CanExecute condition. 的确是这样-如果您不想使用CommandManager.RequerySuggested ,它的确可能会比必要的调用CanExecute更高-您需要显式调用自己的InvokeCanExecute方法,以强制命令重新评估其CanExecute条件。

However, in most cases the CanExecute condition will depend on public (bindable) properties, meaning properties that raise the PropertyChanged event to indicate that their value has changed - it is possible to hook into this event, in order to automatically call InvokeCanExecute whenever one of the properties the command depends on has changed. 但是,在大多数情况下, CanExecute条件将取决于公共(可绑定)属性,这意味着引发PropertyChanged事件以指示其值已更改的PropertyChanged -可以挂接到此事件,以便在InvokeCanExecute任何一种情况下自动调用InvokeCanExecute命令所依赖的属性已更改。 For an example of how to implement such a command, see this guy's blog post (if I'm not mistaken, this approach is implemented eg as part of the MVVM Light toolkit). 有关如何实现命令的示例,请参见此人的博客文章 (如果我没记错的话,例如,作为MVVM Light工具包的一部分,实现了这种方法)。

Instantiating a command using this approach would look somewhat like the following: 使用这种方法实例化命令看起来类似于以下内容:

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

Since the command's CanExecute condition (which checks whether Name is empty) depends on the Name property, it needs to be re-evaluated whenever Name 's content changes. 由于命令的CanExecute条件(检查Name是否为空)取决于Name属性,因此只要Name的内容更改,就需要重新评估该条件。 You simply pass a reference to the Name property to the command's constructor, and InvokeCanExecute will automatically be called whenever the value of Name changes. 您只需将对Name属性的引用传递给命令的构造函数,并且只要Name的值更改, InvokeCanExecute将自动被调用。

In theory, it is possible to go one step further and let the command itself check on which properties it depends - if you're interested in this approach, check out one of my blog articles , but note that this one heavily depends on reflection so it always depends on the detailed use-case whether this approach is feasible or not. 从理论上讲,可以更进一步,让命令本身检查依赖于哪些属性-如果您对此方法感兴趣,请参阅我的博客文章之一 ,但请注意,这一内容很大程度上取决于反射,因此这种方法是否可行始终取决于详细的用例。 A sample implementation of this solution is included in the MVVMbasics framework (disclaimer: published by me). 该解决方案的示例实现包含在MVVMbasics框架中 (免责声明:由我发布)。 In this case, you could reduce the command initialization code to: 在这种情况下,您可以将命令初始化代码减少为:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 ICommand.CanExecute async - ICommand.CanExecute async RelayCommand ICommand.CanExecute不触发 - Relaycommand ICommand.CanExecute not firing 在这种情况下如何调用ICommand.CanExecute? - How to call ICommand.CanExecute in this case? 在WPF中,如何将参数传递给ICommand.CanExecute() - In WPF, how to pass a parameter to ICommand.CanExecute() 即使设置了CommandParameter,ICommand.CanExecute也会传递null - ICommand.CanExecute being passed null even though CommandParameter is set MVVM ICommand.CanExecute参数包含先前的值 - MVVM ICommand.CanExecute parameter contains previous value 尽管ICommand.CanExecute计算为true,但按钮已禁用 - Button disabled although ICommand.CanExecute evaluates to true 为什么ButtonBase在测试`ICommand.CanExecute`之前不检查其可见性? - Why ButtonBase doesn't check its Visibility before testing `ICommand.CanExecute`? 当我将CommandParameter设置为某个Binding时,为什么我的ICommand.CanExecute(object)参数为null,但当我将其设置为某个静态值时为非null? - Why is my ICommand.CanExecute(object) parameter null when I set CommandParameter to some Binding, but non-null when I set it to some static value? 带有可选 canExecute 的异步 ICommand 实现 - Asyncronous ICommand implementation with optional canExecute
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM