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