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

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

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

1 组件安装

1.1 NuGet包管理器安装:

image-20240625110819315

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>

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>

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>

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>

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()

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

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 - 在原始树上进行查询及修改;

TestTree searchResult = testTree.Search(node => node.Name.StartsWith("vect"), true);

Traversal(Action<TTreeNode> expression)

树遍历方法。

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

testTree.Traversal(node => Console.WriteLine(node.Name));

SafeTraversal(Action<TTreeNode> expression)

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

testTree.SafeTraversal(node =>
{
    if (node.Name.EndsWith("1"))
    {
        node.Parent.Children.Remove(node);
    }
});

Filter(Func<TTreeNode, bool> expression)

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

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

testTree.Filter(n => n.Name.Contains(SearchText));

Zhy.Components.ObservableTree.Filter

4 样例源码

TestTreeNode.cs

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

<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

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));
            }
        }
    }
}

相关推荐

  1. QTreeWidget

    2024-07-09 17:12:13       25 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-09 17:12:13       51 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-09 17:12:13       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-09 17:12:13       44 阅读
  4. Python语言-面向对象

    2024-07-09 17:12:13       55 阅读

热门阅读

  1. 大二暑假 + 大三上

    2024-07-09 17:12:13       22 阅读
  2. Git 常用命令及其作用

    2024-07-09 17:12:13       25 阅读
  3. Docker

    Docker

    2024-07-09 17:12:13      21 阅读
  4. C++多线程学习笔记

    2024-07-09 17:12:13       24 阅读
  5. 实现基于Spring Cloud的事件驱动微服务

    2024-07-09 17:12:13       23 阅读
  6. js使用websocket,vue使用websocket,copy即用

    2024-07-09 17:12:13       22 阅读
  7. PostgreSQL的扩展(extensions)-常用的扩展-pg_profile

    2024-07-09 17:12:13       26 阅读