【问题标题】:Bind multiple views to multiple viewmodels将多个视图绑定到多个视图模型
【发布时间】:2012-06-15 13:49:06
【问题描述】:

我有一个显示不同自定义视图的 WPF 窗口。到目前为止,我能够使用我学到的关于 MVVM 的所有知识 :)

现在我遇到了一个新的“问题”:我在更大的视图中有 10 个相同视图的实体。这十个视图实体包含一组控件(文本框、组合框等),但都是一致的。

那么如何将这些 View 绑定到 ViewModel?

我考虑在“更高级别”的 ViewModel 中拥有 10 个 ViewModel 实例,并为视图修复定义 VM 的实例作为数据上下文。

我现在的问题是 --> 是否有更简单(或更方便)的方式将许多(相同)视图绑定到它们的视图模型?

代码示例:

查看模型:

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 个 vwPanel 只是放置在 Grid 内的 StackPanel 中。

正如您所指出的,这与显示数据无关,列表视图或数据网格是一个更好的起点。这是我需要这么多输入控件的特殊情况:/

UPDATE2: 我希望的更像是定义一个 ViewModel 列表并将我的 10 个视图绑定到这个列表之一。但这行不通吗?至少我不知道如何在 XAML 列表中引用一个“特殊”实体...

【问题讨论】:

  • 大视图中的十个视图是专门定义的吗?换句话说,您是否有任何理由不能创建一个 List 并将该 List 绑定到您的 ViewModel 的 IEnumerable 并让它们以这种方式显示?
  • @Tim 我需要它们以正确的顺序输入和输出以正确的顺序。如果没有专门定义它们,这可能吗?

标签: c# wpf user-interface mvvm


【解决方案1】:

通常我使用隐式DataTemplatesViews 映射到ViewModels。他们可以进入&lt;Application.Resources&gt;&lt;Window.Resources&gt;,甚至可以进入特定元素下,例如&lt;TabControl.Resources&gt;

<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 更改?
  • @chiffre,VM 在您的 itemsControl 中显示的顺序是它们添加到 ItemsSource 集合中的确切顺序。因此,使用 Rachel 的示例,如果您将 3 个视图模型添加到“面板”,它们将按照您添加它们的顺序显示。当您选择第一个并更改其属性时,Panels 索引 0 中的视图模型将更改该属性。至于当你的更高级别的VM更改另一个VM时通知视图,只要你的VM正确实现INotifyPropertyChanged就可以了。
  • @chiffre 我不是 100% 确定我理解你的问题。据我了解,您的 VM 包含 10 个 PanelViewModel 属性,您希望使用完全相同的 Panel UserControl 显示这些属性。根据您的面板在 VM 中的列出方式,您可以使用 ItemsControl(如果它们存储在 ObservableCollection)或 ContentControl(如果它们存储在 10 个单独的属性中)来显示它们. PanelUserControl 后面的 DataContext 将是任何 PanelViewModel 绑定到的,所以是的,当父 VM 更新时它们将显示正确的数据
  • 现在我想我明白你的意思了!这实际上可以工作 - 我稍后会尝试使用不同的 ItemControls 等,因为我需要让它们自动折叠等等。所以我必须弄清楚要使用什么。非常感谢!!
【解决方案2】:

如果我正确理解了您的问题,那么您将收集一些您可以在视觉上表示的内容。也就是说,您有几个要为其定义单个视图的视图模型,但要显示 X 次。您的示例显示您使用面板作为“PanelViewModel”的视图...vwPanel 的父项控件是什么?假设您使用的是 ListBox 之类的东西,您可以定义一个包含您的 vwPanel 的自定义 DataTemplate 并将该 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}" />

我尚未验证这是否有效。

【讨论】:

    猜你喜欢
    • 2012-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多