将多个视图绑定到多个视图模型

5
我有一个WPF窗口,可以显示不同的自定义视图。迄今为止,我能够使用我所学习的所有MVVM内容:)
现在我遇到了一个新的“问题”:在一个更大的视图中有10个相同视图的实体。这十个视图实体包含一组控件(文本框、组合框等),但都是一致的。
那么我该如何将这些视图绑定到ViewModel?
我考虑在“高级”ViewModel中有10个ViewModel实例,并将视图固定定义为VM实例作为数据上下文。
我的问题是->是否有更简单(或更方便)的方法来将许多(相同的)视图绑定到它们的ViewModels? 代码示例: 视图模型:
private PanelViewModel _panelViewModel1 = new PanelViewModel();
public PanelViewModel PanelVM1
{
   get { return _panelViewModel1; }
}  

视图示例:

<myControls:vwPanel HorizontalAlignment="Left" x:Name="vwPanel1" 
                    VerticalAlignment="Top" DataContext="{Binding Path=PanelVM1}"/>

我困扰的是,我需要为十个视图编写十次这个逻辑吗?
更新:回答一些问题:我想展示一个视图10次(在我的例子中)。我通过继承UserControl来定义了自己的视图。所以我的vwPanel继承自UserControl。这10个vwPanels只是放置在Grid中的StackPanel内。
这不是关于显示数据的问题,正如你指出的那样,ListView或DataGrid是更好的起点。这是一个需要大量输入控件的特殊情况 :/
更新2:我希望能像定义ViewModels列表一样,将我的10个视图绑定到其中一个列表。但这行不通,对吧?至少我不知道如何在XAML中引用列表中的“特殊”实体...

1
这十个视图在更大的视图中是否有特别定义?换句话说,为什么不能创建一个列表并将该列表绑定到您的ViewModels的IEnumerable,以便以这种方式显示它们? - Tim
@Tim,我需要它们按正确顺序排列,以便按正确顺序进行输入和输出。如果没有特别定义它们,这是否可能? - basti
2个回答

8

通常我使用隐式DataTemplates来将Views映射到ViewModels。它们可以放在<Application.Resources><Window.Resources>甚至只能放在特定元素下,例如<TabControl.Resources>

<DataTemplate DataType="{x:Type local:PanelViewModel}">
    <myControls:vwPanel />
</DataTemplate>

这意味着只要WPF在VisualTree中遇到类型为PanelViewModel的对象,它就会使用vwPanel绘制它。
通常是通过ItemsSource属性将对象放置在VisualTree中。
<ItemsControl ItemsSource="{Binding CollectionOfAllPanels}" />

或者通过使用ContentControl

<ContentControl Content="{Binding PanelVM1}" />

但我仍然能够“识别”它们吗?我的意思是在MVVM中,你有V->VM->M的顺序。使用您的解决方案,我的视图是否知道其正确的VM?特别是如果VM中的属性被其更高级别的VM更改了? - basti
@chiffre,VM在itemsControl中显示的顺序是它们添加到ItemsSource集合的确切顺序。因此,使用Rachel的示例,如果您将3个viewmodel添加到“Panels”,它们将按您添加它们的顺序显示。当您选择第一个并更改其属性时,Panels中索引0的viewmodel将具有该属性的更改。至于当您的高级VM更改另一个VM时通知视图,只要您的VM正确实现了INotifyPropertyChanged,就不会有问题。 - Thelonias
@chiffre 我不完全确定我理解你的问题。据我所知,您的VM包含10个“PanelViewModel”属性,您希望使用完全相同的“Panel”UserControl显示它们。根据面板在VM中的列表方式,您可以使用类似于“ItemsControl”的东西来显示它们(如果它们存储在“ObservableCollection”中),或者使用“ContentControl”(如果它们存储在10个单独的属性中)。 “PanelUserControl”背后的“DataContext”将是其绑定到的任何“PanelViewModel”,因此当父VM更新时,它们将显示正确的数据。 - Rachel
现在我想我明白你的意思了!这个方法实际上可能行得通 - 我稍后会尝试使用不同的ItemControls等进行测试,因为我需要让它们自动折叠等。所以我需要找出该使用什么。非常感谢!! - basti

1
如果我正确理解您的问题,您有一些东西的集合,想要以可视化方式表示它们。也就是说,您有几个视图模型,想要为其定义单个视图,但显示X次数。您的示例显示您将面板用作“PanelViewModel”的视图... vwPanel的父项控件是什么?假设您使用类似ListBox的东西,您可以定义一个自定义DataTemplate,其中包含您的vwPanel,并将该DataTemplate分配给您的ListBox.ItemTemplate。

例如:

<Window.Resources>
    <DataTemplate x:Key="myVMTemplate" TargetType="{x:Type myViewModels:PanelViewModel}">
        <myControls:vwPanel HorizontalAlignment="Left" VerticalAlignment="Top"/>
    </DataTemplate>
</Window.Resources>

<ListBox ItemsSource="{Binding Path=MyCollectionOfPanelVMs}" 
         ItemTemplate="{StaticResource myVMTemplate}" />

我还没有验证这是否有效。


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