在 TreeView 中显示分层数据
Display Hierarchical Data in TreeView
我只是想在 TreeView 中显示分层数据,但我只是想不出如何让它显示比前两个级别更多的内容。 (而且我几乎阅读了所有 TreeView post,也许问题是我在这种情况下对绑定的(遗漏)轻描淡写)
我已经为这个测试简化了我的数据结构:
public class Node
{
public List<Node> Children { get; set; }
public Node Parent { get; set; }
public string Expression { get; set; }
}
Xaml 目前看起来像这样:(请注意,我现在已经更改了几次,但这是我想出的原始状态:)
<Window x:Class="Klammern_Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Klammern_Test"
Title="MainWindow" Height="439" Width="402">
<Window.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Node}">
<TreeViewItem ItemsSource="{Binding Children}" Header="{Binding Expression}"/>
</HierarchicalDataTemplate>
</Window.Resources>
<Grid>
<TreeView ItemsSource="{Binding Root}" Margin="12,41,12,12" Name="treeView" />
</Grid>
</Window>
这就是我尝试填充 Treeview 的方式:
public partial class MainWindow : Window
{
public Node Root { get; set; }
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
private void StartButton_Click(object sender, RoutedEventArgs e)
{
Parser = new StringParser();
Root = Parser.Parse(Tbx_Eingabe.Text);
treeView.Items.Add(PopulateTreeView(Root));
}
private TreeViewItem PopulateTreeView(Node node)
{
TreeViewItem treeViewItem = new TreeViewItem();
treeViewItem.IsExpanded = true;
treeViewItem.Header = node.Expression;
foreach (Node child in node.Children)
{
treeViewItem.Items.Add(new TreeViewItem() { Header = child.Expression });
if (child.Children.Count > 0)
{
PopulateTreeView(child);
}
}
return treeViewItem;
}
}
我错过了什么?
编辑:
在尝试了 almulo 的提示后,我用 Snoop-tool 找到了这个,但我根本不知道它是什么意思,我没有发现其他红线,也没有任何 Binding Errors 列的条目.
在 HierarchicalDataTemplate
中使用 TreeViewItem
,这是您的 TreeView 的 TreeViewItems 将用来创建它们自己的东西......令人困惑。
在您的 HierarchicalDataTemplate
中,您应该只添加您希望项目 "header" 具有的控件。在这种情况下,我想它应该是 TextBlock
因为你只想显示一些文本。
然后使用 HierarchicalDataTemplate.ItemSource
属性 绑定您节点的子节点。
<Window.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Node}"
ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Expression}" />
</HierarchicalDataTemplate>
</Window.Resources>
此外,在您的代码隐藏中,您不应直接操作 TreeView.Items
或 TreeViewItem.Items
,因为您已经在使用绑定和 ItemsSource
属性。
相反,删除 PopulateTreeView
方法并让您的 Root
属性 作为 TreeView 的项目源。但是为了让它起作用,您必须在 Root
属性 更改其值时通知视图。
为此,实现 INotifyPropertyChanged
接口并在每次 Root
更改时触发 PropertyChanged
事件。
编辑: ItemsControl 属性 ItemsSource
需要一个集合(更具体地说,IEnumerable
),所以 Root
需要是一个。即使它只有一个项目,像这样:
public class MainWindow : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
// ...
private void StartButton_Click(object sender, RoutedEventArgs e)
{
Parser = new StringParser();
Root = new Node[] { Parser.Parse(Tbx_Eingabe.Text) };
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Root"));
}
// ...
}
我只是想在 TreeView 中显示分层数据,但我只是想不出如何让它显示比前两个级别更多的内容。 (而且我几乎阅读了所有 TreeView post,也许问题是我在这种情况下对绑定的(遗漏)轻描淡写)
我已经为这个测试简化了我的数据结构:
public class Node
{
public List<Node> Children { get; set; }
public Node Parent { get; set; }
public string Expression { get; set; }
}
Xaml 目前看起来像这样:(请注意,我现在已经更改了几次,但这是我想出的原始状态:)
<Window x:Class="Klammern_Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Klammern_Test"
Title="MainWindow" Height="439" Width="402">
<Window.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Node}">
<TreeViewItem ItemsSource="{Binding Children}" Header="{Binding Expression}"/>
</HierarchicalDataTemplate>
</Window.Resources>
<Grid>
<TreeView ItemsSource="{Binding Root}" Margin="12,41,12,12" Name="treeView" />
</Grid>
</Window>
这就是我尝试填充 Treeview 的方式:
public partial class MainWindow : Window
{
public Node Root { get; set; }
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
private void StartButton_Click(object sender, RoutedEventArgs e)
{
Parser = new StringParser();
Root = Parser.Parse(Tbx_Eingabe.Text);
treeView.Items.Add(PopulateTreeView(Root));
}
private TreeViewItem PopulateTreeView(Node node)
{
TreeViewItem treeViewItem = new TreeViewItem();
treeViewItem.IsExpanded = true;
treeViewItem.Header = node.Expression;
foreach (Node child in node.Children)
{
treeViewItem.Items.Add(new TreeViewItem() { Header = child.Expression });
if (child.Children.Count > 0)
{
PopulateTreeView(child);
}
}
return treeViewItem;
}
}
我错过了什么?
编辑:
在尝试了 almulo 的提示后,我用 Snoop-tool 找到了这个,但我根本不知道它是什么意思,我没有发现其他红线,也没有任何 Binding Errors 列的条目.
在 HierarchicalDataTemplate
中使用 TreeViewItem
,这是您的 TreeView 的 TreeViewItems 将用来创建它们自己的东西......令人困惑。
在您的 HierarchicalDataTemplate
中,您应该只添加您希望项目 "header" 具有的控件。在这种情况下,我想它应该是 TextBlock
因为你只想显示一些文本。
然后使用 HierarchicalDataTemplate.ItemSource
属性 绑定您节点的子节点。
<Window.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Node}"
ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Expression}" />
</HierarchicalDataTemplate>
</Window.Resources>
此外,在您的代码隐藏中,您不应直接操作 TreeView.Items
或 TreeViewItem.Items
,因为您已经在使用绑定和 ItemsSource
属性。
相反,删除 PopulateTreeView
方法并让您的 Root
属性 作为 TreeView 的项目源。但是为了让它起作用,您必须在 Root
属性 更改其值时通知视图。
为此,实现 INotifyPropertyChanged
接口并在每次 Root
更改时触发 PropertyChanged
事件。
编辑: ItemsControl 属性 ItemsSource
需要一个集合(更具体地说,IEnumerable
),所以 Root
需要是一个。即使它只有一个项目,像这样:
public class MainWindow : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
// ...
private void StartButton_Click(object sender, RoutedEventArgs e)
{
Parser = new StringParser();
Root = new Node[] { Parser.Parse(Tbx_Eingabe.Text) };
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Root"));
}
// ...
}