只读属性(例如:IsSelected)和MVVM中的Model

6
考虑一个使用MVVM编写的WPF应用程序。该应用程序需要显示员工列表(名字,姓氏,职位),您可以选择多个进行删除。
在这种情况下,模型将是“Employee”,并且它将实现INotifyPropertyChanged。
视图将是“EmployeeListView”,它将实现XAML以显示一组员工。
ViewModel将是“EmployeeListViewModel”,它将公开一个ObservableCollection,可以将其绑定到EmployeeListView。
我的问题是:“IsSelected”属性应该放在哪里?
1. 在模型中?(我不喜欢这个想法,因为模型现在暴露了一个仅由视图需要且与实际域对象无关的属性,而且如果我以不同的方式实现视图并且不允许一次删除多个员工,则此属性将无用)。 2. 作为单独的字典集合在“EmployeeListViewModel”中,用于跟踪是否选择了员工? (甚至只是包含所有已选员工的HashSet)。我不太喜欢这个,因为视图中的绑定不再直接。 3. 实现一个单独的EmployeeViewModel,它包装Employee对象并公开IsSelected属性。然后,EmployeeListViewModel将其集合公开为ObservableCollection。我最喜欢这个解决方案,但我一直认为每个视图都有一个ViewModel,在这种情况下,我为我的视图有2个ViewModel。这是MVVM模式的偏离还是实现MVVM的典型方式?(参考资料?)
1个回答

8
创建一个可重用的通用SelectableItem,将EmployeeList中的每个项目包装起来:
简单示例:
public class SelectableItem<T>: INotifyPropertyChanged
{
    public bool IsSelected {get;set;} //PropertyChanged(), etc

    public T Value {get;set;}
}

然后在ViewModel中:

public ObservableCollection<SelectableItem<Employee>> Employees {get;set;}

在视图中:

<DataTemplate>
   <CheckBox IsChecked="{Binding IsSelected}" Content="{Value.FullName}"/>
</DataTemplate>

然后你可以通过以下方式检索所有已选择的员工:

var selectedemployees = Employees.Where(x => x.IsSelected).Select(x => x.Value);

我确实喜欢这个解决方案。但是,尽管我询问了如何实现IsSelected,我的问题也涉及到在MVVM中是否可以使用多个ViewModel来使用一个View。此外,SelectableItem不是一个ViewModel吗?如果是这样,那么这与我的解决方案#3类似,只是以一种更通用的方式实现了它。 (如果我有更多的UI特定项要跟踪-IsChecked,IsSelected等,并且并非所有UI都需要跟踪这些不同的属性) - Raj Rao
4
在一个视图中拥有多个虚拟机是完全可接受的。事实上,您可以认为视图上的每个控件本身都是一个视图。最好的例子是当您拥有一个数据网格(DataGrid)时,每一行将拥有自己的虚拟机。 - Sacha Bruttin
1
如果我能回到五年前告诉自己一件事,那就是永远不要害怕将某些东西变成视图模型! - Simon_Weaver
我更喜欢使用 Item 而不是 Value,因为 Value 可能会与可空类型混淆。 - Simon_Weaver

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接