到目前为止,我只使用过 XAML 绑定到预定义
ApplicationCommands
等的应用程序,方法是在视图的代码隐藏中为 Executed
和 CanExecute
定义命令事件处理程序。这听起来总是违反 MVVM,我没有权力反对,但现在我可能会考虑将所有命令逻辑移出并移入视图模型。或者这是命令的错误位置?
为此,我是否必须为每个命令创建 RoutedCommand
类的新子级(每个视图/视图模型可能有数十个)?或者它的父类是错误的,必须使用其他一些父类?一旦我这样做了,我如何通知它现在可以通过 XAML 绑定如此简单地工作的 Executed
和 CanExecute
事件处理程序?
例如,我可以继续使用 ApplicationCommands.Open
并仅在视图模型代码中定义其事件处理程序吗?我找不到从 C# 分配它们的方法。
我已经研究了十多个类似的问题和答案,但没有发现任何具体解决这个问题的内容,因为大多数都涉及我一直在做的事情:绑定到现有命令。
在 WPF / MVVM 中创建命令可以分为 2 部分。
1] 在您的库中,编写一个基类来实现
ICommand
接口。
最基本的形式是
public class Command: ICommand
{
private readonly Action _execute;
public Command(Action execute)
{
_execute = execute;
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_execute?.Invoke();
}
public event EventHandler CanExecuteChanged;
}
还有更高级的形式,允许命令中的逻辑根据应用程序中的某些其他状态(例如来自 CommunityToolkit.Mvvm 库的 RelayCommand)来确定当前是否可以执行该命令。
2] 在视图模型中,为每个所需命令添加一个属性和相应的方法来实现它
例如
public class MyViewModel
{
public MyViewModel()
{
GetDataCommand = new Command( ()=>OnGetData() );
}
// bind this to the Command property of your button / menu item / etc.
public ICommand GetDataCommand {get;}
private void OnGetData()
{
// get the data and update the appropriate properties in the view model
}
}
有关如何在 WPF / MVVM 中实现命令的更多详细信息,请查看我的博客文章。