📅  最后修改于: 2020-11-19 05:24:04             🧑  作者: Mango
在本章中,我们将学习如何向MVVM应用程序添加交互性以及如何干净地调用逻辑。您还将看到,所有这些都是通过保持松耦合和良好的结构来完成的,这是MVVM模式的核心。要了解所有这些,首先让我们了解命令。
命令模式已被很好地记录下来,几十年来经常使用设计模式。在这种模式下,有两个主要参与者,调用者和接收者。
调用程序是一段可以执行命令式逻辑的代码。
通常,它是用户在UI框架的上下文中与之交互的UI元素。
它可能只是应用程序中其他地方的另一段逻辑代码。
接收方是在调用方激发时旨在执行的逻辑。
在MVVM的上下文中,接收器通常是ViewModel中需要调用的方法。
在这两者之间,您有一个阻塞层,这意味着调用者和接收者不必显式地彼此了解。通常将其表示为暴露给调用者的接口抽象,并且该接口的具体实现能够调用接收者。
让我们看一个简单的示例,在该示例中,您将学习命令以及如何使用它们在View和ViewModel之间进行通信。在本章中,我们将继续上一章中的相同示例。
在StudentView.xaml文件中,我们有一个ListBox,它连接ViewModel中的学生数据。现在,我们添加一个按钮,用于从列表框中删除学生。
重要的是使用按钮上的命令非常容易,因为它们具有可挂接到ICommand的command属性。
因此,我们可以在ViewModel上公开一个具有ICommand的属性,并通过按钮的command属性将其绑定,如以下代码所示。
让我们在您的项目中添加一个新类,该类将实现ICommand接口。以下是ICommand接口的实现。
using System;
using System.Windows.Input;
namespace MVVMDemo {
public class MyICommand : ICommand {
Action _TargetExecuteMethod;
Func _TargetCanExecuteMethod;
public MyICommand(Action executeMethod) {
_TargetExecuteMethod = executeMethod;
}
public MyICommand(Action executeMethod, Func canExecuteMethod){
_TargetExecuteMethod = executeMethod;
_TargetCanExecuteMethod = canExecuteMethod;
}
public void RaiseCanExecuteChanged() {
CanExecuteChanged(this, EventArgs.Empty);
}
bool ICommand.CanExecute(object parameter) {
if (_TargetCanExecuteMethod != null) {
return _TargetCanExecuteMethod();
}
if (_TargetExecuteMethod != null) {
return true;
}
return false;
}
// Beware - should use weak references if command instance lifetime
is longer than lifetime of UI objects that get hooked up to command
// Prism commands solve this in their implementation
public event EventHandler CanExecuteChanged = delegate { };
void ICommand.Execute(object parameter) {
if (_TargetExecuteMethod != null) {
_TargetExecuteMethod();
}
}
}
}
如您所见,这是ICommand的简单委托实现,我们有两个委托,一个代表executeMethod,一个代表canExecuteMethod,可以在构造中传递。
在上面的实现中,有两个重载的构造函数,一个仅用于executeMethod,一个同时用于executeMethod和cancanMethod。
让我们在StudentView Model类中添加MyICommand类型的属性。现在我们需要在StudentViewModel中构造一个实例。我们将使用带有两个参数的MyICommand的重载构造函数。
public MyICommand DeleteCommand { get; set;}
public StudentViewModel() {
LoadStudents();
DeleteCommand = new MyICommand(OnDelete, CanDelete);
}
现在添加OnDelete和CanDelete方法的实现。
private void OnDelete() {
Students.Remove(SelectedStudent);
}
private bool CanDelete() {
return SelectedStudent != null;
}
我们还需要添加一个新的SelectedStudent,以便用户可以从ListBox中删除Selected Item。
private Student _selectedStudent;
public Student SelectedStudent {
get {
return _selectedStudent;
}
set {
_selectedStudent = value;
DeleteCommand.RaiseCanExecuteChanged();
}
}
以下是ViewModel类的完整实现。
using MVVMDemo.Model;
using System.Collections.ObjectModel;
using System.Windows.Input;
using System;
namespace MVVMDemo.ViewModel {
public class StudentViewModel {
public MyICommand DeleteCommand { get; set;}
public StudentViewModel() {
LoadStudents();
DeleteCommand = new MyICommand(OnDelete, CanDelete);
}
public ObservableCollection Students {
get;
set;
}
public void LoadStudents() {
ObservableCollection students = new ObservableCollection();
students.Add(new Student { FirstName = "Mark", LastName = "Allain" });
students.Add(new Student { FirstName = "Allen", LastName = "Brown" });
students.Add(new Student { FirstName = "Linda", LastName = "Hamerski" });
Students = students;
}
private Student _selectedStudent;
public Student SelectedStudent {
get {
return _selectedStudent;
}
set {
_selectedStudent = value;
DeleteCommand.RaiseCanExecuteChanged();
}
}
private void OnDelete() {
Students.Remove(SelectedStudent);
}
private bool CanDelete() {
return SelectedStudent != null;
}
}
}
在StudentView.xaml中,我们需要在ListBox中添加SelectedItem属性,该属性将绑定到SelectStudent属性。
以下是完整的xaml文件。
编译并执行上述代码后,您将看到以下窗口。
您会看到删除按钮被禁用。当您选择任何项目时,它将启用。
选择任何项目并按Delete键。您将看到所选项目列表已删除,并且删除按钮再次变为禁用状态。
我们建议您逐步执行上述示例,以更好地理解。