仅查看属性(例如:IsSelected)和MVVM中的模型

Raj*_*Rao 6 wpf design-patterns model mvvm

考虑使用MVVM编写的WPF应用程序.应用程序需要显示Employees列表(FirstName,LastName,Title),您可以选择要删除的多个.

在这种情况下,模型将是" Employee ",它将实现INotifyPropertyChanged.

View将是" EmployeeListView ",它将实现XAML以显示Employees的集合.

ViewModel将是" EmployeeListViewModel ",它将公开一个ObservableCollection,它可以绑定到EmployeeListView.

我的问题是:" IsSelected "财产应该在哪里居住?

  1. 在模型中?(我不喜欢这个想法,因为模型现在暴露了一个只有视图所需的属性而且与实际的域对象无关,而且,如果我以不同的方式实现视图并且不允许,这个属性将是无用的一次删除多名员工).
  2. 在" EmployeeListViewModel "中作为单独的Dictionary集合,它将跟踪是否选择了员工?(或者甚至只是包含所有选定员工的HashSet).我不喜欢这个,因为视图中的绑定不再是直截了当的.
  3. 实现一个单独的EmployeeViewModel,它包装Employee对象并公开IsSelected属性.然后EmployeeListViewModel将其集合公开为ObservableCollection.我最喜欢这个解决方案,但我一直认为每个View有一个ViewModel,在这种情况下,我的视图有2个视图模型.这是偏离MVVM模式还是这是实现MVVM的典型方式?(参考?)

Fed*_*gui 6

创建一个可重用的Generic SelectableItem,它包装EmployeeList中的每个项目:

简单的例子:

public class SelectableItem<T>: INotifyPropertyChanged
{
    public bool IsSelected {get;set;} //PropertyChanged(), etc

    public T Value {get;set;}
}
Run Code Online (Sandbox Code Playgroud)

然后在ViewModel中:

public ObservableCollection<SelectableItem<Employee>> Employees {get;set;}
Run Code Online (Sandbox Code Playgroud)

并在视图中:

<DataTemplate>
   <CheckBox IsChecked="{Binding IsSelected}" Content="{Value.FullName}"/>
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)

然后您可以通过以下方式检索所有选定的员工

var selectedemployees = Employees.Where(x => x.IsSelected).Select(x => x.Value);
Run Code Online (Sandbox Code Playgroud)

  • 在View上拥有多个VM是完全可以接受的.实际上,您可以认为View上的每个控件都是View本身.最好的例子是当你有一个DataGrid时,每一行都有自己的VM. (4认同)