WPF,MVVM,将TreeView绑定到专有树

WPF, MVVM, binding TreeView to proprietary tree

关于WPF和MVVM模式使用WPF的大多数(到目前为止)文章描述了将TreeView绑定到具有相同元素的树,例如 http://www.codeproject.com/Articles/26288/Simplifying-the-WPF-TreeView-by-Using-the-ViewMode。

在这些教程中,只有一个类,其中包含相同类型的孩子,例如具有父母和孩子的"人"类。 TreeView使用HierarchicalDataTemplate绑定到单个类。

如果可以选择不同的类来构建一棵树怎么办? 例如,考虑这样的xml:

1
2
3
    <b x=2>
        <c x=3 />
        <c x=3 />

因此,每个xml元素都包装在不同的类中:类A,B和C。

如何正确编写XAML来绑定那些?

为了显示XAML下面的前2层是合适的:

1
2
3
4
5
6
7
8
9
10
11
<TreeView ItemsSource="{Binding As}">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Bs}">
             <TreeViewItem>
                 <TreeViewItem.Header>
                    <TextBlock Text="{Binding x}" />
                 </TreeViewItem.Header>
             </TreeViewItem>
         </HierarchicalDataTemplate>
     </TreeView.ItemTemplate>
  </TreeView>

但是如何包含第三层,即C?


解决方案是按层次结构包含HierarchicalDataTemplates,如http://blogs.msdn.com/b/mikehillberg/archive/2009/10/30/treeview-and-hierarchicaldatatemplate-step-by-step.aspx中所述。


在WPF的单个集合中显示不同的数据类型时,我们使用DataTemplate s定义每种类型的外观。但是我们只能应用一个DataTemplate,我听到您大喊……如果我们不指定x:Key值,就不会。因此,解决方案很简单...为每种数据类型定义一个DataTemplate,而不必对它们中的任何一个设置x:Key值-这样,框架将隐式地将它们应用于各个项目。

1
2
3
<DataTemplate DataType="{x:Type SomePrefix:SomeType}">
    ...
</DataTemplate>

...

1
2
3
<DataTemplate DataType="{x:Type SomePrefix:AnotherType}">
    ...
</DataTemplate>

解决方案的最后一部分是确保所有数据类型都扩展您需要创建的基类:

1
public class SomeType : BaseDataType { ... }

...

1
public class AnotherType: BaseDataType { ... }

现在,您可以将此BaseDataType类型的集合数据绑定到您的TreeView,并用任何扩展基类的类填充它:

1
public ObservableCollection<BaseDataType> Items { get; set; }

...

1
2
Items.Add(new SomeType());
Items.Add(new AnotherType());

...

1
<TreeView ItemsSource="{Binding Items}" ... />