我有一个显示DataGrid
的视图,该视图绑定到ViewModel中的ObservableCollection
。为了便于讨论,我们假设我们有一个包含团队Team
的{{1}}视图,其中每行代表一个DataGrid
。
我的问题是我应该使用什么数据类型来代表我的Player
集合中的玩家。集合中的项目是ViewModels本身是一个好主意吗?在这种情况下,我的Team
视图会与单个Team
ViewModel以及任意数量的Team
ViewModel(在Team集合中)相关联。
将多个ViewModel与单个View相关联是否违反了MVVM的任何设计指南,是否有实现此方案的首选方法?
谢谢!
答案 0 :(得分:36)
不,那没关系;每个对象本身应该是一个ViewModel。它使代码更清晰,更好的交互,并记住,如果它运作良好,那么它是正确的(即使它违反指南)。
我会按照您的处方方式完成。我将网格绑定到Team
,其中ObservableCollection<Player>
,Player
是另一个ViewModel类。每个行项都会将Player
作为其DataContext
,因此您仍然可以按照您的预期绑定到ViewModel属性:并且Player
仍然可以拥有public
属性ICommand
s(可能是RelayCommands)进行操作!
希望有所帮助!
答案 1 :(得分:11)
远非违反指导方针,我认为这是推荐的设计。至少在我的项目中,你会反复看到这种模式。
此模式与DataTemplates结合使用时特别有用。例如,您可以在您的Application.Resources中为您的PlayerViewModel定义一个DataTemplate,如下所示:
<DataTemplate DataType="viewModels:PlayerViewModel">
<StackPanel Orientation="Vertical">
<Image Source="/Images/Player.png"/>
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
然后,如果你想显示一个玩家列表,你只需将ListBox等绑定到你的TeamViewModel.Players ObservableCollection,你就会自动获得为每个玩家显示的上述DataTemplate:
<ListBox ItemsSource="{Binding Players}"/>
答案 2 :(得分:3)
我同意其他两个答案(Kieren和Groky的答案),但觉得他们没有在这个决定中提到一个非常重要的考虑因素。
如果有关于您正在执行的操作的特定于视图的内容,则应该只创建视图模型。如果您所做的只是绑定到数据并调用自然属于您的模型的命令,则没有理由创建视图模型。
例如,假设:
在这种情况下,在视图和模型之间添加视图模型毫无意义。这样的视图可以直接绑定到模型:
请注意,您可能不想将Delete按钮绑定到Delete()方法,而是将其Command设置为ApplicationCommands.Delete,并使用CommandBinding调用Delete()方法。
我的观点是,在大多数情况下,如果您的模型设计良好,则无需插入视图模型对象。只有在需要跟踪视图特定状态时(例如“当前播放器”),转换太复杂而无法通过简单绑定处理,或者您需要影响多个不同模型对象和/或视图的命令时,才真正需要视图模型模型属性同时。
根据我的经验,如果模型设计正确,只有大约50%左右的所有视图实际上需要一个视图模型,而对于列表中的项目,这更像是20%。
您可以对列表中的项目使用视图模型的时间示例是,您需要保留单独的“选定”标记,该标记是视图的一部分,而不是模型的标记,以及基本功能ListBox是不够的。
答案 3 :(得分:0)
按照简洁的代码原则,将一个视图模型与一个视图相关联是很好的。应该将每个视图的关注点分离开,将来维护代码库会容易得多。