WPF的TreeViewItem获取它的父节点,item.Parent获取的值为null

WPF的TreeViewItem获取它的父节点,item.Parent获取的值为null
大家有碰到过这个问题嘛,遍历数据集合这个方法有点low

阅读 6.1k
1 个回答

修改了一下,右边的TreeView是用数据绑定

写了一个WpfApp1.MainWindow.AncestorHelper类用来从可视树中查找需要的类型

MainWindow.xaml

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <HierarchicalDataTemplate DataType="{x:Type local:Node}" ItemsSource="{Binding Items}">
            <TextBlock Text="{Binding Title}"/>
        </HierarchicalDataTemplate>
    </Window.Resources>
    <Grid Margin="10,10,10,0">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="auto"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <TreeView x:Name="treeView" SelectedItemChanged="TreeView_SelectedItemChanged"/>
        <TreeView Grid.Column="1" x:Name="bindingTreeView" TreeViewItem.Selected="BindingTreeView_Selected">
            <TreeView.ItemContainerStyle>
                <Style TargetType="{x:Type TreeViewItem}">
                    <Setter Property="IsSelected" Value="{Binding IsSelected}"/>
                </Style>
            </TreeView.ItemContainerStyle>
        </TreeView>
        <StatusBar Grid.Row="1" Grid.ColumnSpan="2" >
            <TextBlock Text="Parent: "/>
            <TextBlock x:Name="txtParent" Text=""/>
        </StatusBar>
    </Grid>
</Window>

MainWindow.xaml.cs

using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace WpfApp1
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        static class AncestorHelper
        {
            public static T FindAncestor<T>(DependencyObject dp) where T : DependencyObject
            {
                DependencyObject current = dp;
                while ((current = VisualTreeHelper.GetParent(current)) != null)
                {
                    if (current is T result)
                    {
                        return result;
                    }
                }
                return null;
            }
        }

        public MainWindow()
        {
            InitializeComponent();


            this.BuildTree();
        }

        private void BuildTree()
        {
            var rootNode = new Node("");
            //var rootNode = new TreeViewItem() { Header = "Root" };
            for (int i = 0; i < 5; i++)
            {
                var topItem = new TreeViewItem() { Header = i.ToString() };
                var topNode = new Node(i.ToString());
                for (int j = 0; j < 4; j++)
                {
                    var tvItem1 = new TreeViewItem() { Header = $"{i}-{j}" };
                    var tvNode1 = new Node($"{i}-{j}");
                    for (int k = 0; k < 3; k++)
                    {
                        var tvItem2 = new TreeViewItem() { Header = $"{i}-{j}-{k}" };
                        tvItem1.Items.Add(tvItem2);

                        var tvNode2 = new Node($"{i}-{j}-{k}");
                        tvNode1.Items.Add(tvNode2);
                    }
                    topItem.Items.Add(tvItem1);
                    topNode.Items.Add(tvNode1);
                }
                this.treeView.Items.Add(topItem);
                rootNode.Items.Add(topNode);
                //rootNode.Items.Add(topNode);
            }
            this.bindingTreeView.ItemsSource = rootNode.Items;
            //this.bindingTreeView.Items.Add(rootNode);
        }

        private void TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            if (e.Source is TreeView treeView)
            {
                if (treeView.SelectedItem is TreeViewItem current)
                {
                    var xpath = new Stack<string>();
                    while (current.Parent is TreeViewItem temp)
                    {
                        current = temp;
                        xpath.Push(current.Header.ToString());
                    }
                    if (xpath.Count > 0)
                    {
                        xpath.Push("");
                        txtParent.Text = string.Join("/", xpath);
                    }
                    else
                    {
                        txtParent.Text = "/";
                    }
                }
            }
        }

        private void BindingTreeView_Selected(object sender, RoutedEventArgs e)
        {
            if (e.OriginalSource is TreeViewItem current)
            {
                var xpath = new Stack<string>();

                while ((current = AncestorHelper.FindAncestor<TreeViewItem>(current)) != null)
                {
                    xpath.Push(current.Header.ToString());
                }
                if (xpath.Count > 0)
                {
                    xpath.Push("");
                    txtParent.Text = string.Join("/", xpath);
                }
                else
                {
                    txtParent.Text = "/";
                }
            }
        }
    }
}

node.cs

using System.Collections.ObjectModel;

namespace WpfApp1
{
    class Node
    {
        public string Title { get; set; }
        public ObservableCollection<Node> Items { get; set; }
        public Node() : this(string.Empty)
        {
        }
        public Node(string title)
        {
            this.Title = title;
            this.Items = new ObservableCollection<Node>();
        }
        public override string ToString()
        {
            return $"WpfApp1.Node[Title: {this.Title}]";
        }
    }
}

图片描述

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进