具有多个DataTemplates的ItemsControl用于viewmodel

时间:2011-03-29 13:08:33

标签: wpf silverlight data-binding mvvm viewmodel

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

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

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

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

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

4 个答案:

答案 0 :(得分:47)

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

然后在您的XAML中,您可以使用DataTemplates属性为相应类型创建不同的DataType,如果将样式放置在资源中,则会自动应用样式。 (您也可以在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>

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

答案 1 :(得分:6)

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

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

答案 2 :(得分:2)

查看数据模板选择器:herehere

答案 3 :(得分:-6)

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