# TreeView 使用文档 本文档介绍 AtomUI TreeView 控件的各种使用方式,示例代码摘自 Gallery 演示程序。 > 📖 Gallery 源码位置:`controlgallery/AtomUIGallery/ShowCases/Views/DataDisplay/TreeViewShowCase.axaml` --- ## 前置准备 在 AXAML 中使用 TreeView,需要引入以下命名空间: ```xml xmlns:atom="https://atomui.net" xmlns:antdicons="https://atomui.net/icons/antdesign" ``` 在 C# 代码中引入: ```csharp using AtomUI.Desktop.Controls; // TreeView, TreeViewItem, TreeItemNode 等 using AtomUI.Controls; // ItemToggleType, TreeNodePath, EntityKey 等共享类型 ``` --- ## 1. 基本用法(直接声明节点) 最简单的方式是在 AXAML 中直接声明 `TreeViewItem` 节点: ```xml ``` **要点**: - `ToggleType="CheckBox"` 启用复选框勾选功能 - `ItemKey` 用于唯一标识节点,配合 `DefaultExpandedPaths` 等路径功能使用 - `IsEnabled="False"` 可禁用特定节点 > 📖 参考:Gallery 中 "Basic" 示例。 --- ## 2. 通过数据模板生成(ItemsSource + TreeDataTemplate) 推荐的 MVVM 数据驱动方式,使用 `ItemsSource` 绑定数据: ```xml ``` ```csharp // Code-behind BasicTplTree.ItemsSource = new List { new TreeItemNode() { Header = "parent 1", ItemKey = "0-0", Children = [ new TreeItemNode() { Header = "parent 1-0", ItemKey = "0-0-0", Children = [ new TreeItemNode() { Header = "leaf 1", ItemKey = "0-0-0-0", IsEnabled = false }, new TreeItemNode() { Header = "leaf 2", ItemKey = "0-0-0-1" } ] }, new TreeItemNode() { Header = "parent 1-1", ItemKey = "0-0-1", Children = [ new TreeItemNode() { Header = "sss", ItemKey = "0-0-1-0" } ] } ] } }; ``` **要点**: - `TreeDataTemplate` 的 `ItemsSource` 绑定到 `Children` 属性实现递归层级展示 - `TreeItemNode` 是 `ITreeItemNode` 的默认实现,支持 `Header`、`ItemKey`、`Children`、`Icon` 等属性 - 使用 ReactiveUI 绑定:`this.OneWayBind(ViewModel, vm => vm.TreeNodes, v => v.BasicTplTree.ItemsSource)` > 📖 参考:Gallery 中 "Generate by template" 示例。 --- ## 3. Block 悬浮模式 设置 `NodeHoverMode="Block"` 使节点悬浮效果扩展到整行: ```xml ``` **要点**: - `NodeHoverMode="Block"` 高亮整个节点行 - `IsIndicatorEnabled="False"` 禁用该节点的勾选指示器(CheckBox 不显示) > 📖 参考:Gallery 中 "Block Node" 示例。 --- ## 4. 显示连接线和图标 通过 `IsShowLine`、`IsShowIcon`、`IsShowLeafIcon`、`IsSwitcherRotation` 属性控制树形结构的视觉展示: ```xml ``` **要点**: - `IsShowLine="True"` 启用节点间连接线 - `IsShowIcon="True"` 显示节点图标 - `IsShowLeafIcon="True"` 显示叶子节点图标 - 当启用连接线时,建议将 `IsSwitcherRotation` 设为 `False`,使用展开/折叠两个不同图标 > 📖 参考:Gallery 中 "Tree with line" 示例。 --- ## 5. 拖拽排序 设置 `IsDraggable="True"` 启用拖拽功能: ```xml ``` **要点**: - 拖拽时显示预览浮层和位置指示线 - 支持拖到节点上方、下方或内部(作为子节点) - 不允许将父节点拖入自身子节点中 > 📖 参考:Gallery 中 "draggable" 示例。 --- ## 6. 自定义展开/折叠图标 通过 `SwitcherRotationIcon` 或 `SwitcherExpandIcon`/`SwitcherCollapseIcon` 属性自定义图标: ```xml ``` > 📖 参考:Gallery 中 "Customize collapse/expand icon" 示例。 --- ## 7. 异步加载 通过 `DataLoader` 属性提供异步加载器,实现展开节点时按需加载子节点: ```xml ``` ```csharp // 初始化根节点 AsyncLoadTree.ItemsSource = new List { new TreeItemNode() { Header = "Expand to load", ItemKey = "0" }, new TreeItemNode() { Header = "Expand to load", ItemKey = "1" }, new TreeItemNode() { Header = "Tree Node", ItemKey = "2", IsLeaf = true } }; // 设置异步加载器 AsyncLoadTree.DataLoader = new TreeItemDataLoader(); ``` ```csharp // 自定义加载器实现 ITreeItemNodeLoader 接口 public class TreeItemDataLoader : ITreeItemNodeLoader { public async Task LoadAsync(ITreeItemNode targetTreeItem, CancellationToken token) { await Task.Delay(1000, token); // 模拟异步加载 return new TreeItemLoadResult { IsSuccess = true, Data = new List { new TreeItemNode() { Header = "Child 1", ItemKey = "child-1" }, new TreeItemNode() { Header = "Child 2", ItemKey = "child-2", IsLeaf = true } }.AsReadOnly() }; } } ``` **要点**: - 必须使用 `ItemsSource` 绑定数据(不支持直接声明 `TreeViewItem` 模式) - 非叶子节点展开时自动调用 `DataLoader`,加载过程中显示旋转图标 - 设置 `IsLeaf = true` 的节点不会触发加载 > 📖 参考:Gallery 中 "load data asynchronously" 示例。 --- ## 8. 搜索过滤 通过设置 `FilterValue` 属性触发树节点搜索过滤: ### 对 ItemsSource 数据源搜索 ```xml ``` ### 对直接声明的节点搜索 ```xml ``` ```csharp private void HandleFilterTreeClicked(object? sender, RoutedEventArgs e) { if (sender is SearchEdit searchEdit) { SearchTreeView.FilterValue = searchEdit.Text?.Trim(); } } ``` **要点**: - 默认使用 `DefaultTreeItemFilter`,按节点 `Header` 文本匹配 - `FilterHighlightStrategy` 控制过滤行为(高亮匹配/隐藏未匹配/展开路径等) - 将 `FilterValue` 设为 `null` 或空字符串可清除过滤 > 📖 参考:Gallery 中 "Searchable" 和 "Searchable by TreeDataTemplate" 示例。 --- ## 9. 默认展开、选中和勾选 通过路径属性指定初始状态: ```csharp // 默认展开路径 myTreeView.DefaultExpandedPaths = new List { new TreeNodePath("0-0/0-0-0"), new TreeNodePath("0-0/0-0-1/0-0-1-1") }; // 默认选中路径 myTreeView.DefaultSelectedPaths = new List { new TreeNodePath("0-0/0-0-1") }; // 默认勾选路径(需配合 ToggleType="CheckBox") myTreeView.DefaultCheckedPaths = new List { new TreeNodePath("0-0/0-0-1/0-0-1-1") }; ``` **路径格式**:使用 `/` 分隔的 `ItemKey` 值,从根节点到目标节点的完整路径。 > 📖 参考:`controlgallery/AtomUIGallery/ShowCases/Views/DataDisplay/TreeViewShowCase.axaml.cs` 中 `InitBasicTreeViewData` 方法。 --- ## 10. 获取选中和勾选数据 ### 获取选中节点 ```csharp // 单选模式 object? selected = myTreeView.SelectedItem; // 多选模式 IList? selectedItems = myTreeView.SelectedItems; ``` ### 获取勾选节点 ```csharp // 获取所有勾选项 IList checkedItems = myTreeView.CheckedItems; ``` ### 监听勾选变化 ```csharp myTreeView.CheckedItemsChanged += (sender, args) => { foreach (var added in args.AddedItems) { Console.WriteLine($"Checked: {added}"); } foreach (var removed in args.RemovedItems) { Console.WriteLine($"Unchecked: {removed}"); } }; ``` --- ## 11. 程序化控制 ### 展开/折叠所有节点 ```csharp // 展开全部(不带动画) myTreeView.ExpandAll(motionEnabled: false); // 展开全部(带动画) myTreeView.ExpandAll(motionEnabled: true); // 折叠全部 myTreeView.CollapseAll(motionEnabled: false); ``` ### 勾选/取消勾选子树 ```csharp // 勾选指定节点及其所有子节点 if (myTreeView.ContainerFromIndex(0) is TreeViewItem item) { myTreeView.CheckedSubTree(item); } // 取消勾选 myTreeView.UnCheckedSubTree(item); ``` --- ## 常见组合模式 ### 文件浏览器风格 ```xml ``` ### 权限配置风格 ```xml ``` ### 搜索 + 异步加载 ```xml ```