.NET C# 树遍历、查询、拷贝与可视化
目录
- .NET C# 树遍历、查询、拷贝与可视化
- 1 组件安装
- 1.1 NuGet包管理器安装:
- 1.2 控制台安装:
- 2 接口
- 1.1 ITree\<TTreeNode\>
- 1.2 ITree\<TKey, TTreeNode\>
- 1.3 IObservableTree\<TTreeNode\>
- 1.4 IObservableTree\<TKey, TTreeNode\>
- 3 方法
- Clone()
- Search(Func\<TTreeNode, bool\> expression, bool isClone = false)
- Traversal(Action\<TTreeNode\> expression)
- SafeTraversal(Action\<TTreeNode\> expression)
- Filter(Func\<TTreeNode, bool\> expression)
- 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>
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));
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><ButtonCommand="{Binding SearchCommand}"Content="查 询"Cursor="Hand"DockPanel.Dock="Right" /><TextBox Text="{Binding SearchText}" /></DockPanel><TreeViewGrid.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"><TextBlockVerticalAlignment="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));}}}
}