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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5473001/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 22:43:04  来源:igfitidea点击:

ItemsControl with multiple DataTemplates for a viewmodel

wpfsilverlightdata-bindingmvvmviewmodel

提问by silverfighter

is it possible to bind an itemscontrol with canvas as template to multiple DataTemplates?

是否可以将带有画布作为模板的项目控件绑定到多个数据模板?

I have 2 collections and depending on the type I would like to display a different control on my canvas.

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

I am not sure but I could think about a Viewmodel which has 2 ObservableCollections. For example if I would have "Shapes" and "connections" and I would like to display them both on the canvas? In case of a diagraming scenario...

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

I would like to do this in the mvvm manner and I am not sure if the multiple DataTemplate approach is correct but this came to my mind. But I am still having problems to get the binding straight in my head. If I set the DataContext to the ViewModel for me it seems not possible to bind 2 collections to the items control... =( I am also open for other ideas, too....

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

Is this possible? And if so, how would the binding look like an

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

回答by H.B.

You can create multiple ObservableCollectionsand then bind your ItemsSourceto a CompositeCollectionwhich joins those collections.

您可以创建多个ObservableCollections,然后将您的绑定ItemsSourceCompositeCollection加入这些集合的一个。

Then in your XAML you can create different DataTemplatesfor the respective types using the DataTypeproperty which like styles gets automatically applied if it is placed in the resources. (You can also create the composite in XAML which is shown on MSDN, if the CollectionContainersshould be bound that is a bit more difficultthough)

然后在您的 XAML 中,您可以DataTemplates使用DataType属性为相应的类型创建不同的样式,如果将样式放置在资源中,则会自动应用该属性。(您也可以在 MSDN 上显示的 XAML 中创建复合,如果CollectionContainers应该绑定的话会有点困难

Example code:

示例代码:

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>

Here i use a different panel but it should be the same for a canvas.

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

回答by Jens

You could have ObservableCollection<object>in your ViewModel and bind the ItemsControl's Source to this collection.

您可以ObservableCollection<object>在 ViewModel 中将 ItemsControl 的 Source 绑定到此集合。

Then, to get a different look for different types of data, you could two DataTemplates without x:Key, but with properly set DataType in your Resources. The ItemsControl will then automatically select the appropriate DataTemplate for your item.

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

回答by TerenceHymanson

Have a look at the Data template selector: hereor here.

查看数据模板选择器:herehere

回答by Joel Cochran

Another option with less code behind would be to define two ListBoxes, each with their own templates and bound to their own collections. Define them each in the same physical space and just control which one is visible based on your state. You could even do this with the Visual State Manager and custom states.

另一个使用较少代码的选择是定义两个 ListBox,每个都有自己的模板并绑定到自己的集合。在相同的物理空间中定义它们,并根据您的状态控制哪个可见。您甚至可以使用 Visual State Manager 和自定义状态来执行此操作。