我想使用过 WPF 的程序员,应该都知道 MVVM 模式。然而,争议最多的是,是否应该在 Model 类中实现 INotifyPropertyChanged 接口。我的结论是:不应该在 Model 类中实现 INotifyPropertyChanged 接口。
Model 代表真实状态内容的领域模型(面向对象),或者代表数据访问层(以数据为中心);View 是用户在屏幕上看到的接口、布局和外观(UI);ViewModel 是暴露公共属性和命令的 View 抽象,View 与 ViewModel 通过绑定器进行通信。
View 类不知道 Model 类的存在,而 ViewModel 和 Model 也不知道 View 是如何设计的。事实上,Model 完全不会知道 ViewModel 和 View 存在的事实。这是一个非常松散耦合的设计,同时,便于对 ViewModel 进行单元测试。
Model 类的设计其实与 MVVM 模式无关。你可以创建一个 ViewModel 类来将任何数据对象调整为对 WPF 友好的东西。Model 类不应该有任何内容表明它正在使用 MVVM 模式 和 WPF 框架。因为,Model 很容易来自遗留业务库。
错误的设计
public class User : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private String name;
public String Name
{
get { return name; }
set
{
if (name != value)
{
RaisePropertyChanged("Name");
}
}
}
private String email;
public String Email
{
get { return email; }
set
{
if (email != value)
{
RaisePropertyChanged("Email");
}
}
}
}
正确的设计
public class User
{
public String Name { get; set; }
public String Email { get; set; }
}
请注意,ViewModel 是 Model 对象的包装器。它通过一组属性公开 Model 的状态,在 View 控件中使用状态。ViewModel 不复制 Model 的状态;它只是通过委托将其公开,如下所示:
public class UserViewModel : INotifyPropertyChanged
{
private readonly User user;
public UserViewModel(User user)
{
this.user = user;
}
public String Name
{
get { return this.user.Name; }
set
{
if (value != this.user.Name)
{
this.user.Name = value;
RaisePropertyChanged("Name");
}
}
}
public String Email
{
get { return this.user.Email; }
set
{
if (value != this.user.Email)
{
this.user.Email = value;
RaisePropertyChanged("Email");
}
}
}
public event PropertyChangedEventHandler? PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
你可以理解为 ViewModel 是一个或多个 Model 的属性包装器,并向 View 暴露公共属性和命令的地方。
为了在 View 上显示项目集合,你需要使用 ObservableCollection<T>。那应该如何设计和使用 ObservableCollection<T> 呢?
错误的设计
public class MultiUserViewModel
{
public ObservableCollection<User> Users { get; private set; } = new ObservableCollection<User>();
}
正确的设计
public class MultiUserViewModel
{
public ObservableCollection<UserViewModel> Users { get; private set; } = new ObservableCollection<UserViewModel>();
}
MVVM 模式的主要核心在 View 和 ViewModel 的交互上。不管我们是否使用 MVVM 模式,Model 都是存在的。其实,MVVM 仅仅是一个指导方针,而不是规则/规范。因此,你在使用 MVVM 模式进行应用程序开发时,在不违背大的理论基础上,可以根据自己的使用场景做一些变动。