用于视图模型的具有多个 DataTemplate 的 ItemsControl

Posted

技术标签:

【中文标题】用于视图模型的具有多个 DataTemplate 的 ItemsControl【英文标题】:ItemsControl with multiple DataTemplates for a viewmodel 【发布时间】:2011-07-25 06:51:53 【问题描述】:

是否可以将带有画布作为模板的itemscontrol绑定到多个DataTemplates?

我有 2 个集合,根据类型,我想在画布上显示不同的控件。

我不确定,但我可以考虑一个具有 2 个 ObservableCollections 的 Viewmodel。例如,如果我有“形状”和“连接”并且我想在画布上显示它们?如果是图表场景...

我想以 mvvm 方式执行此操作,我不确定多 DataTemplate 方法是否正确,但我想到了这一点。 但是我仍然无法将绑定直接放在脑海中。如果我为我将 DataContext 设置为 ViewModel,似乎无法将 2 个集合绑定到项目控件... =( 我也对其他想法持开放态度......

这可能吗?如果是这样,绑定看起来像一个

【问题讨论】:

您是否需要 BOTH 用于 WPF 和 Silverlight? 从长远来看两者都不错...但第一个 WPF 会很棒... DataTemplateSelector 将适用于 WPFSilverlight 【参考方案1】:

您可以创建多个ObservableCollections,然后将您的ItemsSource 绑定到加入这些集合的CompositeCollection

然后在您的 XAML 中,您可以使用 DataType 属性为各自的类型创建不同的 DataTemplates,如果将其放置在资源中,则会自动应用类似的样式。 (您也可以在 MSDN 上显示的 XAML 中创建复合材料,但如果 CollectionContainers 应该绑定为 a bit more difficult)

示例代码:

ObservableCollection<Employee> data1 = new ObservableCollection<Employee>(new Employee[]

    new Employee("Hans", "Programmer"),
    new Employee("Elister", "Programmer"),
    new Employee("Steve", "GUI Designer"),
    new Employee("Stefan", "GUI Designer"),
    new Employee("Joe", "Coffee Getter"),
    new Employee("Julien", "Programmer"),
);
ObservableCollection<Machine> data2 = new ObservableCollection<Machine>(new Machine[]

    new Machine("E12", "GreedCorp"),
    new Machine("E11", "GreedCorp"),
    new Machine("F1-MII", "CommerceComp"),
    new Machine("F2-E5", "CommerceComp")
);
CompositeCollection coll = new CompositeCollection();
coll.Add(new CollectionContainer()  Collection = data1 );
coll.Add(new CollectionContainer()  Collection = data2 );
Data = coll;
<ItemsControl ItemsSource="Binding Data">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.Resources>
        <DataTemplate DataType="x:Type local:Employee">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="Binding Name"/>
                <TextBlock Text=" ("/>
                <TextBlock Text="Binding Occupation"/>
                <TextBlock Text=")"/>
            </StackPanel>
        </DataTemplate>
        <DataTemplate DataType="x:Type local:Machine">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="Binding Model"/>
                <TextBlock Text=" - "/>
                <TextBlock Text="Binding Manufacturer"/>
            </StackPanel>
        </DataTemplate>
    </ItemsControl.Resources>
</ItemsControl>

这里我使用不同的面板,但对于画布应该是相同的。

【讨论】:

很遗憾,COmpositeCollection 不适用于 UWP 框架。 如果Employee和Machine类都继承自同一个类X,则不需要CompositeCollection,一个X的ObservableCollection就足够了。 @Viliam:当然,但这是一个主要假设,在很多情况下都不成立。【参考方案2】:

您可以在 ViewModel 中包含 ObservableCollection&lt;object&gt; 并将 ItemsControl 的 Source 绑定到此集合。

然后,为了获得不同类型数据的不同外观,您可以使用两个不带 x:Key 的 DataTemplate,但在资源中正确设置 DataType。然后,ItemsControl 将自动为您的项目选择适当的 DataTemplate。

【讨论】:

【参考方案3】:

查看数据模板选择器:here 或 here.

【讨论】:

【参考方案4】:

另一个减少代码的选项是定义两个 ListBox,每个都有自己的模板并绑定到自己的集合。在相同的物理空间中定义它们,并根据您的状态控制哪个是可见的。您甚至可以使用可视状态管理器和自定义状态来做到这一点。

【讨论】:

以上是关于用于视图模型的具有多个 DataTemplate 的 ItemsControl的主要内容,如果未能解决你的问题,请参考以下文章

分页列表不适用于具有多个模型的视图

绑定到 DataTemplate 中的视图模型属性

具有多个模型的 MVC3 视图

MVVM + Datacontext + DataTemplate + Blend = 问题

在一个页面上将一个视图模型拆分为多个表单

具有相同模型的主干多个视图