在这种情况下如何调用ICommand.CanExecute?

dot*_*NET 3 .net c# wpf xaml mvvm

好.这是场景.这是WPF + MVVM(.net 4.0)应用程序:

  1. 查看:有一个DataGrid和两个按钮上移/下移,这些按钮应该向上或向下移动选定的记录DataGrid.网格和按钮都使用基于XAML的绑定.
  2. ViewModel:具有DataViewDataGrid将绑定的类型的公共属性.然后,ICommand下面列出了两个实现.这两个按钮将绑定到这两个命令.最后但并非最不重要的是,有两个函数被调用MoveUp()并且MoveDown()显而易见.
  3. 两个ICommand实现:在每个命令中,CanExecute()返回所选记录是否可以分别向上或向下Execute()移动,并实际通过调用上面描述的ViewModel MoveUp()MoveDown()函数来移动记录.这些命令对象在其构造函数中获取VM对象的引用.

首先,我想知道这个架构是否正确并符合MVVM模式?其次,手头的问题是当我更改选定的记录时,我的按钮没有启用/禁用DataGrid,这带来了两个子问题:

  1. 谁打电话CanExecute()和何时?
  2. 我怎样才能手动调用它?我CommandManager.InvalidateRequerySuggested()在阅读了其他一些SO问题后尝试过,但这也无济于事.

这是我的CommandBase类,我的Command类都从这个类继承:

internal abstract class CommandBase : DependencyObject, ICommand
{
    public virtual bool CanExecute(Object parameter)
    {
        return true;
    }

    public abstract void Execute(Object parameter);
    public event EventHandler CanExecuteChanged;

    protected void OnCanExecuteChanged(Object sender, EventArgs e)
    {
        CanExecuteChanged(sender, e);
    }
}
Run Code Online (Sandbox Code Playgroud)

Roh*_*ats 6

我想知道这个架构是否正确并符合MVVM模式?

是的,这完全符合MVVM模式.


谁调用CanExecute()以及什么时候?

每当CanExecuteChanged引发事件时都会调用CanExecute().

命令内部挂钩此事件并启用/禁用按钮或任何基于CanExecute委托返回的bool属性的frameworkElement.


我怎样才能手动调用它?

首先RaiseCanExecuteChanged()在具体实现中创建方法(如果还没有),以便可以手动调用它.这将是这样的:

    public void RaiseCanExecuteChanged()
    {
        EventHandler canExecuteChangedHandler = CanExecuteChanged;
        if (canExecuteChangedHandler != null)
        {
           canExecuteChangedHandler(this, EventArgs.Empty);
        }
    }
Run Code Online (Sandbox Code Playgroud)

因为在您的情况下,CanExecute()只要DataGrid中的SelectedItem发生更改,您就需要调用.我建议将SelectedItemDataGrid 绑定到ViewModel中的某个属性,并在setter中手动调用RaiseCanExecuteChanged(),以便可以在命令实例上调用CanExecute.


但是,如果您不想手动调用RaiseCanExecuteChanged()方法,还有另一种方法.CommandManager.RequerySuggested只要CommandManager感觉UI需要刷新,您就可以挂钩到引发的事件.

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }
Run Code Online (Sandbox Code Playgroud)

RequerySuggested事件在System.Windows.Input.CommandManager检测到可能更改命令执行能力的条件时发生 .

所以,每当CommandManager.RequerySuggested被提出,它最终会提高你CanExecuteChanged从而调用CanExecute你的命令.因此,启用/禁用基于CanExecute委托返回的bool的按钮.