简单的嵌套 TreeView Xaml 结构?
Posted
技术标签:
【中文标题】简单的嵌套 TreeView Xaml 结构?【英文标题】:Simple Nested TreeView Xaml structure? 【发布时间】:2015-05-13 15:39:54 【问题描述】:我正在尝试构建一个具有三层的 WPF TreeView
。 CountryReportTitle
是一个字符串属性,ArticleCategoryTitlesList
是一个集合,两者都暴露于我的ViewModel
。没有定义类层次结构。这是我正在寻找的结构:
这是我尝试的 Xaml,但我在运行时在 Xaml 中遇到异常:
"Item has already been added. Key in dictionary: 'DataTemplateKey(ISESApp.ViewModels.ReportViewModel)' Key being added: 'DataTemplateKey(ISESApp.ViewModels.ReportViewModel)'"
Xaml:
<TreeView ItemsSource="Binding CountryReportTitle">
<TreeView ItemsSource="Binding CountryReportTitle">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="x:Type local:ReportViewModel"
ItemsSource="Binding ArticleCategoryTitlesList">
<TextBlock Text="Binding CategoryTitle" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="x:Type local:ReportViewModel"
ItemsSource="Binding ArticleCatagoryTypesList">
<TextBlock Text="Binding ArticleTitle" />
</HierarchicalDataTemplate>
<DataTemplate DataType="x:Type local:ReportViewModel">
<TextBlock Text="Binding ArticleTitle" />
</DataTemplate>
</TreeView.Resources>
</TreeView>
</TreeView>
Local: 是我的 ViewModel 的命名空间:
xmlns:local="clr-namespace:MyApp.ViewModels"
我做错了什么,解决这个问题的最佳方法是什么?
【问题讨论】:
【参考方案1】:这是树视图的首选示例。
对树中的元素使用HierarchicalDataTemplate
。请注意,共有三层,每一层都有自己的类型。这是为了方便起见,但您可以为树定义一种类型并使用一个模板或任何类型的组合。不同的类型代表树中的不同事物,使用模板非常方便。
数据类
public class ViewModel
public ObservableCollection<ItemA> ItemsA get; set;
public ViewModel()
ItemsA = new ObservableCollection<ItemA>(new[]
new ItemAName = "A one",
new ItemAName = "A Two",
new ItemAName = "A Three",
);
public class ItemA
public ObservableCollection<ItemB> ItemsB get; set;
public string Name get; set;
public ItemA()
ItemsB = new ObservableCollection<ItemB>(new[]
new ItemBName = "B one",
new ItemBName = "B Two",
new ItemBName = "B Three",
);
public class ItemB
public ObservableCollection<ItemC> ItemsC get; set;
public string Name get; set;
public ItemB()
ItemsC = new ObservableCollection<ItemC>(new[]
new ItemCName = "C one",
new ItemCName = "C Two",
new ItemCName = "C Three",
);
public class ItemC
public string Name get; set;
还有用户界面
<TreeView ItemsSource="Binding ItemsA">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="x:Type t:ItemA"
ItemsSource="Binding ItemsB">
<TextBlock Text="Binding Name" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="x:Type t:ItemB"
ItemsSource="Binding ItemsC">
<TextBlock Text="Binding Name" />
</HierarchicalDataTemplate>
<DataTemplate DataType="x:Type t:ItemC">
<TextBlock Text="Binding Name" />
</DataTemplate>
</TreeView.Resources>
</TreeView>
给你一个简单的树视图
【讨论】:
谢谢。我的两个收藏都在同一个 viewModel 中。我真的不想分成不同的班级。如果是这样,我将如何定义 DataType? @Hardgraf 假设 ItemsB 在 ViewModel 上而不是在 ItemA 中。您必须为 ItemA 绑定回 HierarchicalDataTemplate 中的 ViewModel--ItemsSource="Binding DataContext.ItemsB, ElementName=root"
,确保为您的 Window 提供x:Name="root"
,以便 ElementName 指向正确的位置。
觉得我快到了。将问题更改为我的新 Xaml,但仍不确定如何为我的每个 HierarchicalDataTemplates 引用正确的 DataTypes。
@Hardgraf 我不知道。从你的问题中不清楚发生了什么。你说事情是错的,但你没有提供关于它是如何出错的信息,如果有错误,等等。
公平点。我当前的代码在问题中。问题是直到运行时我才知道每个列表将包含什么,因此 TreeView 需要在运行时动态构建。我认为我的问题是我设置 DataType- DataType="x:Type local:ReportViewModel" 我不认为这是正确的,但我不确定如何将每个 HierarchicalDataTemplate 绑定到正确的列表中视图模型【参考方案2】:
您需要在 TreeView 中绑定 TreeView 资源:
<TreeView.Resources>
<HierarchicalDataTemplate
DataType="x:Type local:FirstLayer"
ItemsSource="Binding Children">
<StackPanel Orientation="Horizontal" Margin="2">
<TextBlock Text="Binding ChildrenName" />
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate
DataType="x:Type local:SecondLayer"
ItemsSource="Binding Children">
<StackPanel Orientation="Horizontal" Margin="2">
<TextBlock Text="Binding ChildrenName" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.Resources>
我认为您需要修改项目以将 Treeview 与 ViewModel 绑定,而不是字符串列表
这是一个很好的Example
【讨论】:
以上是关于简单的嵌套 TreeView Xaml 结构?的主要内容,如果未能解决你的问题,请参考以下文章
TreeView ItemSsource 绑定到 ViewModel 不更新 xaml 控件项
如何在 Xaml 中使用 SortDescriptions 对 TreeView 项目进行排序?
使用treeview.js插件生成树状菜单方法的简单介绍(附通过json字符串生成菜单的代码)