[英]How to call ICommand.CanExecute in this case?
好。 这是场景。 这是WPF + MVVM(.net 4.0)应用程序:
DataGrid
和两个按钮上移/下移,这些按钮应该在DataGrid
向上或向下移动选定的记录。 网格和按钮都使用基于XAML的绑定。 DataView
类型的公共属性,我的DataGrid
将绑定到该属性。 然后,下面列出了两个ICommand
实现。 这两个按钮将绑定到这两个命令。 最后但并非最不重要的是,有两个名为MoveUp()
和MoveDown()
函数可以做到这一点。 ICommand
实现:在每个命令中, CanExecute()
返回所选记录是否可以分别向上或向下移动,并且Execute()
实际上通过调用上面描述的ViewModel的MoveUp()
和MoveDown()
函数来移动记录。 这些命令对象在其构造函数中获取VM对象的引用。 首先,我想知道这个架构是否正确并符合MVVM模式? 其次,当我在DataGrid
更改所选记录时,我的按钮没有被启用/禁用,这带来了两个子问题:
CanExecute()
以及什么时候? 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);
}
}
我想知道这个架构是否正确并符合MVVM模式?
是的,这完全符合MVVM模式。
谁调用CanExecute()以及什么时候?
每当CanExecuteChanged
事件时,都会调用CanExecute()。
命令内部挂钩此事件并启用/禁用按钮或任何基于CanExecute委托返回的bool属性的frameworkElement 。
我怎样才能手动调用它?
首先在具体实现中创建RaiseCanExecuteChanged()
方法(如果还没有),以便可以手动调用它。 这将是这样的:
public void RaiseCanExecuteChanged()
{
EventHandler canExecuteChangedHandler = CanExecuteChanged;
if (canExecuteChangedHandler != null)
{
canExecuteChangedHandler(this, EventArgs.Empty);
}
}
因为在您的情况下,只要dataGrid中的SelectedItem发生更改,您就需要调用CanExecute()
。 我建议将DataGrid的SelectedItem
绑定到ViewModel中的某个属性,并在setter中手动调用RaiseCanExecuteChanged()
,以便可以在命令实例上调用RaiseCanExecuteChanged()
。
但是,如果您不想手动调用RaiseCanExecuteChanged()
方法,还有另一种方法。 您可以挂钩CommandManager.RequerySuggested
事件,只要CommandManager
感觉需要刷新UI,就会引发该事件。
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
RequerySuggested事件在System.Windows.Input.CommandManager检测到可能更改命令执行能力的条件时发生。
因此,每当引发CommandManager.RequerySuggested
时,它最终会引发CanExecuteChanged
从而调用命令的CanExecute
。 因此,启用/禁用基于CanExecute委托返回的bool的按钮。
用这个替换'OnExcuteChanged'......
public event EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
我个人总是使用Josh Smith的实现RelayCommand
:
internal class RelayCommand : ICommand
{
private readonly Action<object> _execute;
private readonly Predicate<object> _canExecute;
public RelayCommand(Action<object> execute) : this(execute, null)
{
}
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
{
throw new ArgumentNullException("execute");
}
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
public void Execute(object parameter)
{
_execute(parameter);
}
}
从这个链接引用CanExecutedChanged
事件:
CanExecuteChanged事件是ICommand接口实现的一部分,具有一些有趣的功能。 它将事件订阅委托给CommandManager.RequerySuggested事件。 这可以确保WPF命令基础结构询问所有RelayCommand对象是否可以在它询问内置命令时执行。
在您的情况下,此事件不起作用,并且对象未收到有关执行命令的可能性的信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.