.NET C# 树遍历、查询、拷贝与可视化

.NET C# 树遍历、查询、拷贝与可视化

目录

  • [.NET C# 树遍历、查询、拷贝与可视化](# 树遍历、查询、拷贝与可视化)
    • [1 组件安装](#1 组件安装)
      • [1.1 NuGet包管理器安装:](#1.1 NuGet包管理器安装:)
      • [1.2 控制台安装:](#1.2 控制台安装:)
    • [2 接口](#2 接口)
      • [1.1 ITree\<TTreeNode\>](#1.1 ITree<TTreeNode>)
      • [1.2 ITree\<TKey, TTreeNode\>](#1.2 ITree<TKey, TTreeNode>)
      • [1.3 IObservableTree\<TTreeNode\>](#1.3 IObservableTree<TTreeNode>)
      • [1.4 IObservableTree\<TKey, TTreeNode\>](#1.4 IObservableTree<TKey, TTreeNode>)
    • [3 方法](#3 方法)
      • Clone()
      • [Search(Func\<TTreeNode, bool\> expression, bool isClone = false)](#Search(Func<TTreeNode, bool> expression, bool isClone = false))
      • [Traversal(Action\<TTreeNode\> expression)](#Traversal(Action<TTreeNode> expression))
      • [SafeTraversal(Action\<TTreeNode\> expression)](#SafeTraversal(Action<TTreeNode> expression))
      • [Filter(Func\<TTreeNode, bool\> expression)](#Filter(Func<TTreeNode, bool> expression))
    • [4 样例源码](#4 样例源码)

树结构组件,支持查询、遍历、拷贝、可视树过滤(不改变树结构,只过滤显示效果)

1 组件安装

1.1 NuGet包管理器安装:

1.2 控制台安装:

NuGet\Install-Package Zhy.Components.Tree -Version 1.0.3
NuGet\Install-Package Zhy.Components.Tree.Extension -Version 1.0.3

2 接口

1.1 ITree<TTreeNode>

csharp 复制代码
public class TestTree : ITree<TestTree>
{
    public string Id { get; set; }
    public string Name { get; set; }
    public TestTree Parent { get; set; }
    public List<TestTree> Children { get; set; }

    public TestTree(string id, string name, TestTree parent, List<TestTree> children)
    {
        Id = id;
        Name = name;
        Parent = parent;
        Children = children;
    }

    public TestTree Clone()
    {
        var childListClone = new List<TestTree>();
        if (Children != null)
        {
            foreach (var child in Children)
            {
                var childClone = child.Clone();
                childClone.Parent = this;
                childListClone.Add(childClone);
            }
        }
        return new TestTree(Id, Name, null, childListClone);
    }
}

1.2 ITree<TKey, TTreeNode>

csharp 复制代码
public class TestTree2 : ITree<string, TestTree2>
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string Key { get; set; }
    public string PKey { get => Parent?.Key; }
    public TestTree2 Parent { get; set; }
    public List<TestTree2> Children { get; set; }

    public TestTree2 this[string key]
    {
        get => Children.First(x => x.Key == key);
        set 
        {
            TestTree2 node = Children.First(x => x.Key == key);
            int idx = Children.IndexOf(node);
            Children[idx] = value;
        }
    }

    public TestTree2(string id, string name, string key, TestTree2 parent, List<TestTree2> children)
    {
        Id = id;
        Name = name;
        Key = key;
        Parent = parent;
        Children = children;
    }

    public TestTree2 Clone()
    {
        var childListClone = new List<TestTree2>();
        if (Children != null)
        {
            foreach (var child in Children)
            {
                var childClone = child.Clone();
                childClone.Parent = this;
                childListClone.Add(childClone);
            }
        }
        return new TestTree2(Id, Name, Key, null, childListClone);
    }
}

1.3 IObservableTree<TTreeNode>

csharp 复制代码
public class TestTree : ITree<TestTree>
{
    public string Id { get; set; }
    public string Name { get; set; }
    public TestTree Parent { get; set; }
    public List<TestTree> Children { get; set; }

    public TestTree(string id, string name, TestTree parent, List<TestTree> children)
    {
        Id = id;
        Name = name;
        Parent = parent;
        Children = children;
    }

    public TestTree Clone()
    {
        var childListClone = new List<TestTree>();
        if (Children != null)
        {
            foreach (var child in Children)
            {
                var childClone = child.Clone();
                childClone.Parent = this;
                childListClone.Add(childClone);
            }
        }
        return new TestTree(Id, Name, null, childListClone);
    }
}

1.4 IObservableTree<TKey, TTreeNode>

csharp 复制代码
public class TestTree2 : ITree<string, TestTree2>
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string Key { get; set; }
    public string PKey { get => Parent?.Key; }
    public TestTree2 Parent { get; set; }
    public List<TestTree2> Children { get; set; }

    public TestTree2 this[string key]
    {
        get => Children.First(x => x.Key == key);
        set
        {
            TestTree2 node = Children.First(x => x.Key == key);
            int idx = Children.IndexOf(node);
            Children[idx] = value;
        }
    }

    public TestTree2(string id, string name, string key, TestTree2 parent, List<TestTree2> children)
    {
        Id = id;
        Name = name;
        Key = key;
        Parent = parent;
        Children = children;
    }

    public TestTree2 Clone()
    {
        var childListClone = new List<TestTree2>();
        if (Children != null)
        {
            foreach (var child in Children)
            {
                var childClone = child.Clone();
                childClone.Parent = this;
                childListClone.Add(childClone);
            }
        }
        return new TestTree2(Id, Name, Key, null, childListClone);
    }
}

3 方法

Clone()

深拷贝方法,继承接口时实现。

csharp 复制代码
TestTree testTree = new TestTree("0", "root", null, new List<TestTree>());
TestTree testTreeClone = testTree.Clone();

Search(Func<TTreeNode, bool> expression, bool isClone = false)

树查询方法。

expression: 委托,参数为树节点,返回值为True/False,表示节点是否符合查询规则;

isClone: 是否克隆新的对象,True - 在新的树上进行查询及修改,并返回新的树,False - 在原始树上进行查询及修改;

csharp 复制代码
TestTree searchResult = testTree.Search(node => node.Name.StartsWith("vect"), true);

Traversal(Action<TTreeNode> expression)

树遍历方法。

expression: 委托,参数为树节点,遍历所有节点执行;

csharp 复制代码
testTree.Traversal(node => Console.WriteLine(node.Name));

SafeTraversal(Action<TTreeNode> expression)

安全的树遍历,若遍历时对树节点结构进行修改时使用。

csharp 复制代码
testTree.SafeTraversal(node =>
{
    if (node.Name.EndsWith("1"))
    {
        node.Parent.Children.Remove(node);
    }
});

Filter(Func<TTreeNode, bool> expression)

可视树过滤,不改变树结构,只影响树结构的可视化显示。

expression: 委托,参数为树节点,返回值为True/False,表示节点是否符合过滤规则;

csharp 复制代码
testTree.Filter(n => n.Name.Contains(SearchText));

4 样例源码

TestTreeNode.cs

csharp 复制代码
using CommunityToolkit.Mvvm.ComponentModel;
using System.Collections.ObjectModel;

namespace Zhy.Components.Tree.Test
{
    public partial class TestTreeNode : ObservableObject, IObservableTree<TestTreeNode>
    {
        public TestTreeNode Parent { get; set; }

        [ObservableProperty]
        private string _name;

        [ObservableProperty]
        private ObservableCollection<TestTreeNode> _children;
        //public ObservableCollection<TestTreeNode> Children 
        //{
        //    get => _children;
        //    set => SetProperty(ref _children, value);
        //}

        public TestTreeNode Clone()
        {
            TestTreeNode clone = new TestTreeNode
            {
                Name = _name,
            };
            if (Children?.Count > 0)
            {
                clone.Children = new ObservableCollection<TestTreeNode>();
                foreach (var child in Children)
                {
                    TestTreeNode subClone = child.Clone();
                    subClone.Parent = this;
                    clone.Children.Add(subClone);
                }
            }
            return clone;
        }
    }
}

MainWindow.xaml

xaml 复制代码
<Grid Margin="10">
    <Grid.RowDefinitions>
        <RowDefinition Height="auto" />
        <RowDefinition />
    </Grid.RowDefinitions>
    <DockPanel>
        <Button
            Command="{Binding SearchCommand}"
            Content="查  询"
            Cursor="Hand"
            DockPanel.Dock="Right" />
        <TextBox Text="{Binding SearchText}" />
    </DockPanel>
    <TreeView
        Grid.Row="1"
        HorizontalContentAlignment="Stretch"
        VerticalContentAlignment="Stretch"
        ItemsSource="{Binding TreeNodes}">
        <TreeView.ItemContainerStyle>
            <Style TargetType="TreeViewItem">
                <Setter Property="IsExpanded" Value="True" />
            </Style>
        </TreeView.ItemContainerStyle>
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding Children}">
                <DockPanel x:Name="dp" Margin="0,2,0,2">
                    <TextBlock
                        VerticalAlignment="Center"
                        FontSize="14"
                        IsHitTestVisible="True"
                        Text="{Binding Name}" />
                    <TextBlock IsHitTestVisible="True" />
                </DockPanel>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>
</Grid>

MainWindowViewModel.cs

csharp 复制代码
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Collections.ObjectModel;
using Zhy.Components.Tree.Extension;

namespace Zhy.Components.Tree.Test
{
    public partial class MainWindowViewModel : ObservableObject
    {
        [ObservableProperty]
        private ObservableCollection<TestTreeNode> _treeNodes;
        [ObservableProperty]
        private string _searchText;

        public MainWindowViewModel()
        {
            _treeNodes = new ObservableCollection<TestTreeNode>
            {
                new TestTreeNode
                {
                    Name = "资源目录",
                    Children = new ObservableCollection<TestTreeNode>
                    {
                        new TestTreeNode
                        {
                            Name = "矢量",
                            Children = new ObservableCollection<TestTreeNode>
                            {
                                new TestTreeNode
                                {
                                    Name = "行政区划",
                                    Children = new ObservableCollection<TestTreeNode>
                                    {
                                        new TestTreeNode
                                        {
                                            Name = "北京行政区划"
                                        },
                                        new TestTreeNode
                                        {
                                            Name = "天津行政区划"
                                        },
                                        new TestTreeNode
                                        {
                                            Name = "河北行政区划"
                                        },
                                    }
                                },
                                new TestTreeNode
                                {
                                    Name = "管线",
                                }
                            }
                        },
                        new TestTreeNode
                        {
                            Name = "栅格",
                            Children = new ObservableCollection<TestTreeNode>
                            {
                                new TestTreeNode
                                {
                                    Name = "正射影像",
                                    Children = new ObservableCollection<TestTreeNode>
                                    {
                                        new TestTreeNode
                                        {
                                            Name = "北京遥感影像"
                                        },
                                        new TestTreeNode
                                        {
                                            Name = "天津遥感影像"
                                        },
                                        new TestTreeNode
                                        {
                                            Name = "河北遥感影像"
                                        },
                                    }
                                },
                                new TestTreeNode
                                {
                                    Name = "DEM"
                                }
                            }
                        }
                    }
                },
            };
        }

        [RelayCommand]
        private void Search()
        {
            foreach (var item in TreeNodes)
            {
                item.Filter(n => n.Name.Contains(SearchText));
            }
        }
    }
}
相关推荐
九鼎科技-Leo2 分钟前
什么是 WPF 中的依赖属性?有什么作用?
windows·c#·.net·wpf
搬砖的小码农_Sky13 分钟前
C语言:数组
c语言·数据结构
Heaphaestus,RC1 小时前
【Unity3D】获取 GameObject 的完整层级结构
unity·c#
baivfhpwxf20231 小时前
C# 5000 转16进制 字节(激光器串口通讯生成指定格式命令)
开发语言·c#
直裾1 小时前
Scala全文单词统计
开发语言·c#·scala
先鱼鲨生2 小时前
数据结构——栈、队列
数据结构
一念之坤2 小时前
零基础学Python之数据结构 -- 01篇
数据结构·python
IT 青年2 小时前
数据结构 (1)基本概念和术语
数据结构·算法
熬夜学编程的小王2 小时前
【初阶数据结构篇】双向链表的实现(赋源码)
数据结构·c++·链表·双向链表
ZwaterZ3 小时前
vue el-table表格点击某行触发事件&&操作栏点击和row-click冲突问题
前端·vue.js·elementui·c#·vue