Wpf 如何在TreeView中显示嵌套关系
努力在我的树视图中显示嵌套关系。以下是场景: 在数据库中,我有Category和Account表。每个类别可以有零个或多个子类别,因此此表与自身具有嵌套关系。每个类别/子类别中可以有零个或多个帐户,类别和帐户之间存在一对多关系。很简单,不是吗 在我的数据库之上,我有EDMX,其中包含类别和帐户实体,以及我上面提到的它们的关联。为了便于理解,我重命名了导航属性,以便类别中现在有ParentCategory、ChildCategories和Accounts属性 在EDMX之上,我有我的ViewModel,它定义了一个名为AllCategories的公共属性。我的TreeView将绑定到此属性。我在启动时初始化此属性,如下所示:Wpf 如何在TreeView中显示嵌套关系,wpf,treeview,hierarchicaldatatemplate,Wpf,Treeview,Hierarchicaldatatemplate,努力在我的树视图中显示嵌套关系。以下是场景: 在数据库中,我有Category和Account表。每个类别可以有零个或多个子类别,因此此表与自身具有嵌套关系。每个类别/子类别中可以有零个或多个帐户,类别和帐户之间存在一对多关系。很简单,不是吗 在我的数据库之上,我有EDMX,其中包含类别和帐户实体,以及我上面提到的它们的关联。为了便于理解,我重命名了导航属性,以便类别中现在有ParentCategory、ChildCategories和Accounts属性 在EDMX之上,我有我的ViewMod
using (MyEntities context = new MyEntities())
Categories = context.Categories.Include(x => x.Accounts).ToList();
最后,我使用以下HierarchycalDataTemplate来显示这些内容:
<HierarchicalDataTemplate DataType = "{x:Type local:Category}" ItemsSource = "{Binding Path=ChildCategories}">
<TreeViewItem Header="{Binding Name}" ItemsSource="{Binding Accounts}" />
</HierarchicalDataTemplate>
<DataTemplate DataType = "{x:Type local:Account}">
<TextBlock Text="{Binding Name}" />
</DataTemplate>
这运行良好,并在树中显示类别、子类别和帐户,但问题是子类别不仅显示在其父类别下,而且显示在根级别。这适用于所有深度的类别。我做错了什么
注意:如果我添加.Wherex=>!x、 在VM中,它仅显示根类别及其直接子级,而不显示其他内容
编辑
下面是它目前的样子。所有的事情都进展顺利,直到我手动添加了那条白线作为插图;与WPF无关。之后,子类别开始与其子类别重复。这个过程一直持续到叶子的子类别。我相信我知道这里发生了什么,但没有解决办法。作为参考,他提出了一个问题的解决方案,但他使用的是数据集,而我使用的是EF,无法将他的解决方案转化为我的场景
其思想是通过ObservableCollections连接您的业务数据,并使您的分层模板保持简单,这样treeview就不会显示重复的条目。 示例代码显示嵌套的viewmodel关系和相应的层次模板。为了简化,根是一个可观察集合,否则您需要在此处添加INotifyPropertyChanged,并在树视图中添加选择性ItemsSource绑定
<Window x:Class="MyWpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyWpf"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<HierarchicalDataTemplate DataType = "{x:Type local:RootItem}" ItemsSource = "{Binding Path=Categories}">
<TextBlock Text="{Binding Header}"></TextBlock>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType = "{x:Type local:CatNode}" ItemsSource = "{Binding Path=Items}">
<TextBlock Text="{Binding Header}"></TextBlock>
</HierarchicalDataTemplate>
</Window.Resources>
<Grid>
<TreeView ItemsSource="{Binding MyRoot}"/>
</Grid>
</Window>
namespace MyWpf
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
MyRoot = new ObservableCollection<RootItem>();
MyRoot.Add(new RootItem());
}
public ObservableCollection<RootItem> MyRoot { get; set; }
}
public class RootItem
{
public RootItem()
{
Categories = new ObservableCollection<CatNode>();
Categories.Add(new CatNode { Header = "Cat1" });
Categories[0].Items.Add("Item11");
Categories[0].Items.Add("Item12");
Categories.Add(new CatNode { Header = "Cat2" });
Categories[1].Items.Add("Item21");
Categories[1].Items.Add("Item22");
}
public string Header { get { return "Root"; }}
public ObservableCollection<CatNode> Categories { get; set; }
}
public class CatNode
{
public CatNode()
{
Items = new ObservableCollection<string>();
}
public string Header { get; set; }
public ObservableCollection<string> Items { get; set; }
}
}
添加另一个包含类别而不是子类别的层次模板。这将是你树视图的根。@deafjeff:谢谢。你能告诉我它是什么样子吗?我不明白你的问题,截图会很有帮助的。此外,您以错误的方式使用HierarchycalDataTemplate,其中的根可视控件应该是标题,因此通常我们需要在该位置使用一些ContentControl,而不是像您当前使用的TreeViewItem那样的Items控件。每个类别都有一个子类别集合和一个帐户集合,那么,您希望如何在一个树状项下显示2个这些集合呢?看来你得先把它们合并起来。@KingKing:我加了一张当前事态的截图。再加上一个指向解决这个问题的codeproject文章的链接。确实非常优雅。我后来发现,我向任何想开始使用WPF TreeView和MVVM的人推荐。尽管那篇文章相当广泛,但基本思想与您阐述的相同。非常感谢。顺便说一句,我也是从那篇文章开始的-