到目前为止,大多数关于使用MVVM模式的WPF的文章都描述了将TreeView绑定到相同元素的树,例如http://www.codeproject.com/Articles/26288/Simplifying-the-WPF-TreeView-by-Using-the-ViewMode.
在这些教程中,只有一个类,它包含相同类型的子类,例如类"person",它有父类和子类。TreeView使用HierarchicalDataTemplate来绑定到单个类。如果有一个不同的类的选择,它们构建一个树。例如,考虑这样的xml:
<a x=1>
<b x=2>
<c x=3 />
<c x=3 />
</b>
</a>
所以每个xml元素被包装成不同的类:类a, B和c。
如何正确地编写XAML绑定那些?
为了显示前2层下面的XAML是合适的:
<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?
当在WPF中显示单个集合中的不同数据类型时,我们使用DataTemplate
s定义每种类型的外观但是我们只能应用一个DataTemplate
我听到你大喊…如果没有指定x:Key
值,则不指定。所以,解决办法很简单……为每个数据类型定义一个DataTemplate
,并且只不设置它们中的任何一个x:Key
值-这样,框架将隐式地将它们应用于单个项目。
<DataTemplate DataType="{x:Type SomePrefix:SomeType}">
...
</DataTemplate>
…
<DataTemplate DataType="{x:Type SomePrefix:AnotherType}">
...
</DataTemplate>
解决方案的最后一部分是确保所有数据类型都扩展了需要创建的基类:
public class SomeType : BaseDataType { ... }
…
public class AnotherType: BaseDataType { ... }
现在您可以将BaseDataType
类型的集合数据绑定到TreeView
,并用扩展基类的任何类填充它:
public ObservableCollection<BaseDataType> Items { get; set; }
…
Items.Add(new SomeType());
Items.Add(new AnotherType());
…
<TreeView ItemsSource="{Binding Items}" ... />
解决方案是分层地包含HierarchicalDataTemplates,如http://blogs.msdn.com/b/mikehillberg/archive/2009/10/30/treeview-and-hierarchicaldatatemplate-step-by-step.aspx所述。