您可能想查看“RelayCommand”——它是 ICommand 的常见实现,可以简化您的视图模型代码,允许您为 ICommand 的“Execute”和“CanExecute”方法指定委托。你会在网上找到很多实现,但这是我使用的:
public class RelayCommand : ICommand
{
private readonly Action<object> _execute;
private readonly Predicate<object> _canExecute;
public RelayCommand(Action<object> execute, Predicate<object> canExecute = null)
{
if (execute == null)
{
throw new ArgumentNullException("execute");
}
this._execute = execute;
this._canExecute = canExecute;
}
public virtual bool CanExecute(object parameter)
{
return this._canExecute == null || this._canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public virtual void Execute(object parameter)
{
this._execute(parameter);
}
}
在您的虚拟机中,公开如下命令:-
public ICommand FooCommand
{
get
{
if (_fooCommand == null)
{
_fooCommand = new RelayCommand(ExecuteFooCommand, CanDoFooCommand);
}
return _fooCommand;
}
}
private void ExecuteFooCommand(object commandParameter)
{
// Code to execute the command.
}
private bool CanDoFooCommand()
{
// Code that indicates whether the command can be executed.
// This will manifest itself in the view by enabling/disabling the button.
}
由于 RelayCommand ctr 参数是委托,你当然可以这样做:-
new RelayCommand(o => { // do something }, o => true);
最后,将你的命令绑定到你的视图按钮:-
<Button Content="Click me" Command="{Binding FooCommand}" ... />
您也可以将参数传递给命令委托:-
<Button Content="Click me" Command="{Binding FooCommand}" CommandParamter="123" />
(凭记忆写出,因此在语法上可能不是 100% 正确!)
更进一步……
为了进一步简化事情,我使用动态属性将 VM 命令公开给视图。在我的 VM 基类中,我具有以下属性:-
public dynamic Commands
{
get
{
return _commands;
}
}
然后在 VM 的构造函数中,我可以像这样创建它的所有命令:-
Commands.FooCommand = new RelayCommand(.....
Commands.BarCommand = ..etc..
在我的 XAML 中,我绑定如下命令:- Command={Binding Commands.FooCommand}。
这是一个节省时间的方法,因为它只是意味着我可以根据需要从单个属性中挂起任意数量的命令,而不是像我之前的示例中那样将每个命令公开为单独的属性。