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

问题描述 投票:0回答:5

是否可以将以canvas为模板的itemscontrol绑定到多个DataTemplate?

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

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

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

这可能吗?如果是这样,绑定会是什么样子

wpf silverlight data-binding mvvm viewmodel
5个回答
62
投票

您可以创建多个

ObservableCollections
,然后将您的
ItemsSource
绑定到连接这些集合的
CompositeCollection

然后在 XAML 中,您可以使用

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

示例代码:

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>

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


5
投票

您可以在 ViewModel 中拥有

ObservableCollection<object>
并将 ItemsControl 的 Source 绑定到此集合。

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


2
投票

查看数据模板选择器:此处这里


0
投票

我相信与公认的解决方案相比,有一种更简单的解决方案,尽管我在桌面应用程序中使用没有 Silverlight 的 WPF:

和之前一样使用ItemsControl,但是让它的模板使用ContentControl,可以方便地根据类型进行动态模板切换。

型号:

public class ViewModel : BindableBase
{
    /*
     *  Other stuff not relevant to the problem
     */

    public ObservableCollection<AbstractType> Properties { get; }
}
public abstract class AbstractType { }
public class ConcreteTypeP : AbstractType { }
public class ConcreteTypeQ : AbstractType { }

查看:

<UserControl>
<!--I didn't include all the namesapce/viewmodel stuff in the UserControl attributes-->

<UserControl.Resources>
<!--These can be defined in a separate file for the sake of reuse. Not exactly sure on the syntax to correctly reference them though.-->
    <DataTemplate DataType="{x:Type local:ConcreteTypeP}">
        <!--text blocks and whatever other stuff go here-->
    </DataTemplate>

    <DataTemplate DataType="{x:Type local:ConcreteTypeQ}">
        <!--text blocks and whatever other stuff go here-->
    </DataTemplate>
</UserControl.Resources>

<DockPanel>
    <ItemsControl DockPanel.Dock="Top"
                  VerticalAlignment="Center"
                  ItemsSource="{Binding Properties}">
        <ItemsControl.ItemTemplate>
            <DataTemplate DataType="{x:Type local:AbstractType}">
                <ContentControl Content="{Binding}"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</DockPanel>

-6
投票

隐藏代码较少的另一个选项是定义两个列表框,每个列表框都有自己的模板并绑定到自己的集合。 将它们分别定义在同一物理空间中,并根据您的状态控制哪一个可见。 您甚至可以使用视觉状态管理器和自定义状态来执行此操作。

© www.soinside.com 2019 - 2024. All rights reserved.