好的。这是场景。这是 WPF + MVVM (.net 4.0) 应用程序:
- View:有一个
DataGrid
和两个按钮 Move Up/Move Down,它们应该在DataGrid
中向上或向下移动选定的记录。网格和按钮都使用基于 XAML 的绑定(bind)。 - ViewModel:具有
DataView
类型的公共(public)属性,我的DataGrid
将绑定(bind)到该类型。然后就是下面列出的两个ICommand
实现。这两个按钮将绑定(bind)到这两个命令。最后但并非最不重要的是,有两个名为MoveUp()
和MoveDown()
的函数可以完成显而易见的任务。 - 两个
ICommand
实现:在每个命令中,CanExecute()
分别返回所选记录是否可以向上或向下移动,Execute()
实际上是通过调用我上面描述的 ViewModel 的MoveUp()
和MoveDown()
函数来移动记录。这些命令对象在其构造函数中获取 VM 对象的引用。
首先,我想知道这个架构是否正确并符合 MVVM 模式?其次,手头的问题是,当我更改 DataGrid
中的选定记录时,我的按钮没有启用/禁用,这带来了 2 个子问题:
- 谁调用
CanExecute()
以及何时调用? - 如何手动调用它?在阅读了一些其他 SO 问题后,我尝试了
CommandManager.InvalidateRequerySuggested()
,但这也没有帮助。
这是我的 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);
}
}
最佳答案
I want to know if this architecture correct and in line with MVVM pattern?
是的,这完全符合 MVVM 模式。
Who calls CanExecute() and when?
只要引发 CanExecuteChanged
事件,就会调用 CanExecute()。
命令在内部 Hook 此事件并启用/禁用按钮或任何基于 CanExecute 委托(delegate)返回的 bool 属性的 frameworkElement。
How can I call it manually?
首先在您的具体实现中创建 RaiseCanExecuteChanged()
方法(如果尚未创建),以便可以手动调用它。这看起来像这样:
public void RaiseCanExecuteChanged()
{
EventHandler canExecuteChangedHandler = CanExecuteChanged;
if (canExecuteChangedHandler != null)
{
canExecuteChangedHandler(this, EventArgs.Empty);
}
}
因为在您的情况下,只要 dataGrid 中的 SelectedItem 发生变化,您就需要调用 CanExecute()
。我建议将 DataGrid 的 SelectedItem
绑定(bind)到您的 ViewModel 和 setter 中的某些属性,您手动调用 RaiseCanExecuteChanged()
以便可以在您的命令实例上调用 CanExecute。
但是,如果您不想手动调用 RaiseCanExecuteChanged()
方法,还有另一种方法。您可以 Hook CommandManager.RequerySuggested
事件,只要 CommandManager
感觉 UI 需要刷新,就会引发该事件。
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
RequerySuggested event Occurs when the System.Windows.Input.CommandManager detects conditions that might change the ability of a command to execute.
因此,无论何时引发 CommandManager.RequerySuggested
,它最终都会引发您的 CanExecuteChanged
,从而调用您的命令的 CanExecute
。因此,基于 CanExecute 委托(delegate)返回的 bool 值启用/禁用按钮。
关于c# - 在这种情况下如何调用 ICommand.CanExecute?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21647872/