与单个视图关联的多个ViewModel

时间:2010-07-15 19:49:33

标签: wpf mvvm

我有一个显示DataGrid的视图,该视图绑定到ViewModel中的ObservableCollection。为了便于讨论,我们假设我们有一个包含团队Team的{​​{1}}视图,其中每行代表一个DataGrid

我的问题是我应该使用什么数据类型来代表我的Player集合中的玩家。集合中的项目是ViewModels本身是一个好主意吗?在这种情况下,我的Team视图会与单个Team ViewModel以及任意数量的Team ViewModel(在Team集合中)相关联。

将多个ViewModel与单个View相关联是否违反了MVVM的任何设计指南,是否有实现此方案的首选方法?

谢谢!

4 个答案:

答案 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的答案),但觉得他们没有在这个决定中提到一个非常重要的考虑因素。

如果有关于您正在执行的操作的特定于视图的内容,则应该只创建视图模型。如果您所做的只是绑定到数据并调用自然属于您的模型的命令,则没有理由创建视图模型。

例如,假设:

  1. 您的Player对象具有Name属性,Rank属性,Promote()方法和Delete()方法。
  2. 您的视图很简单,可以让您编辑任何玩家的名称和等级,还有按钮来提升和删除玩家。
  3. 在这种情况下,在视图和模型之间添加视图模型毫无意义。这样的视图可以直接绑定到模型:

    • 将TextBox.Text绑定到Name属性
    • 将Slider.Value绑定到Rank属性
    • 将Promote按钮绑定到Promote()方法
    • 将删除按钮绑定到Delete()方法

    请注意,您可能不想将Delete按钮绑定到Delete()方法,而是将其Command设置为ApplicationCommands.Delete,并使用CommandBinding调用Delete()方法。

    我的观点是,在大多数情况下,如果您的模型设计良好,则无需插入视图模型对象。只有在需要跟踪视图特定状态时(例如“当前播放器”),转换太复杂而无法通过简单绑定处理,或者您需要影响多个不同模型对象和/或视图的命令时,才真正需要视图模型模型属性同时。

    根据我的经验,如果模型设计正确,只有大约50%左右的所有视图实际上需要一个视图模型,而对于列表中的项目,这更像是20%。

    您可以对列表中的项目使用视图模型的时间示例是,您需要保留单独的“选定”标记,该标记是视图的一部分,而不是模型的标记,以及基本功能ListBox是不够的。

答案 3 :(得分:0)

按照简洁的代码原则,将一个视图模型与一个视图相关联是很好的。应该将每个视图的关注点分离开,将来维护代码库会容易得多。