当前位置: 首页 > news >正文

Avalonia treedatagrid使用杂记

这里只对最近使用到的分层树做一些记录,有复选框示例,支持父级选中状态改变子集同步变化

废话不多说,直接上源码

View布局

                <TreeDataGridHeight="710"BorderBrush="Gray"CanUserResizeColumns="False"FontSize="16"Source="{Binding TreeDataGridSource}"><TreeDataGrid.Resources><DataTemplate x:Key="CheckBoxCellTemplate" x:DataType="vm:TreeDataModel"><CheckBox IsChecked="{Binding IsSelected, Mode=TwoWay}" /></DataTemplate></TreeDataGrid.Resources></TreeDataGrid>

model对象

    public class TreeDataModel : INotifyPropertyChanged{private string _name;public string Name{get { return _name; }set{_name = value;OnPropertyChanged(nameof(Name));}}private int? _age;public int? Age{get { return _age; }set{_age = value;OnPropertyChanged(nameof(Age));}}public bool _isSelected;public bool IsSelected{get { return _isSelected; }set{_isSelected = value;OnPropertyChanged(nameof(IsSelected));// 如果是分类节点,更新所有子项的状态if (IsCategory){foreach (var child in Children){child.IsSelected = value;}}}}private string _department;public string Department{get => _department;set{if (_department != value){_department = value;OnPropertyChanged(nameof(Department));}}}private string _category;public bool IsCategory => !string.IsNullOrEmpty(Category);public bool IsExpanded { get; set; } = true;public string Category{get { return _category; }set{_category = value;OnPropertyChanged(nameof(Category));}}private ObservableCollection<TreeDataModel> _children = new ObservableCollection<TreeDataModel>();public ObservableCollection<TreeDataModel> Children{get { return _children; }set{_children = value;OnPropertyChanged(nameof(Children));}}public event PropertyChangedEventHandler? PropertyChanged;protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}protected bool SetField<T>(ref T field, T value, [CallerMemberName] string? propertyName = null){if (EqualityComparer<T>.Default.Equals(field, value)) return false;field = value;OnPropertyChanged(propertyName);return true;}}

vm 数据刷新逻辑

    private HierarchicalTreeDataGridSource<TreeDataModel> _treeDataGridSource =new HierarchicalTreeDataGridSource<TreeDataModel>(new List<TreeDataModel>());public HierarchicalTreeDataGridSource<TreeDataModel> TreeDataGridSource{get { return _treeDataGridSource; }set{_treeDataGridSource = value;OnPropertyChanged(nameof(TreeDataGridSource));}}private TreeDataModel selectedItem;public TreeDataModel SelectedItem{get => selectedItem;set{selectedItem = value;OnPropertyChanged(nameof(SelectedItem));}}public async void InitTreeData(){List<TreeDataModel> data = new List<TreeDataModel>();for (int i = 0; i < 10; i++){int value = 10 + i;data.Add(new TreeDataModel(){Age = value,Name = $"示例{value}",Department = "测试部",});}for (int i = 0; i < 7; i++){int value = 10 + i;data.Add(new TreeDataModel(){Age = value,Name = $"张三{value}",Department = "研发",});}for (int i = 23; i < 50; i++){int value = 10 + i;data.Add(new TreeDataModel(){Age = value,Name = $"酒香也怕巷子深{value}",Department = "心如止水",});}//聚合形成树形数据集var categoryGroups = data.GroupBy(i =>{// 按照"-"前面的部分分类var dashIndex = i.Department.IndexOf('-');return dashIndex > 0 ? i.Department.Substring(0, dashIndex) : i.Department;});List<TreeDataModel> listData = new List<TreeDataModel>();foreach (var group in categoryGroups){var category = new TreeDataModel { Category = group.Key };foreach (var item in group){category.Children.Add(item);}listData.Add(category);}TreeDataGridSource =new HierarchicalTreeDataGridSource<TreeDataModel>(listData){Columns ={new HierarchicalExpanderColumn<TreeDataModel>(new TextColumn<TreeDataModel, string>("人员",x => x.IsCategory ? $"{x.Category}({x.Children.Count}成员)" : x.Name,GridLength.Auto),x => x.Children,isExpandedSelector: x => x.IsExpanded),new TextColumn<TreeDataModel, int?>("年龄",x => x.Age,GridLength.Auto),new TemplateColumn<TreeDataModel>("","CheckBoxCellTemplate", // 使用自定义模板
                        width: GridLength.Auto),},};TreeDataGridSource.RowSelection.SelectionChanged += (s, e) =>{if (s is TreeDataGridRowSelectionModel<TreeDataModel> selec){if (selec.SelectedItem is TreeDataModel selectModel){SelectedItem = selectModel;}}};}

关键点,

1.数据格式绑定基本都在vm完成treedatagrid数据源集合需要绑定HierarchicalTreeDataGridSource,而不是传统的ObservableCollection

2.行选中时间SelectionChanged,控件不支持直接使用SelectionChanged,需要vm业务层订阅RowSelection来引出SelectionChanged,数据集每次变化都需要重新订阅

3.复选框:

        数据集Columns绑定时其实有CheckBoxColumn列,不过这里演示通过绑定资源键的形式 x:Key="CheckBoxCellTemplate"实现复选框

        父级状态改变影响子集,Avalonia原本的TreeDataGrid并没有对这个实现,但是自己可以通过通过对IsSelected属性变化时,验证IsCategory是否是分类节点 从而更改子集选中状态

 

http://www.wooajung.com/news/35448.html

相关文章:

  • 【汇总】接口自动化测试 + 持续集成(文末视频演示)
  • IBM SPSS Amos 29下载安装教程来了!从下载到激活一步不漏
  • 一文看懂开源Coze如何让测试效率飙升
  • word文档修改标记
  • 高压电线电力巡检六类图像识别数据集(2000张图片已划分、已标注)【数据集分享】
  • 零代码构建智能体!Dify插件打通AI Agent开发全链路
  • 酵母双杂交:解析蛋白质互作的经典工具
  • Java or Python?测试开发工程师如何选择合适的编程语言?
  • 深入理解 LangGraph:构建复杂智能体的状态管理与执行流
  • ./build.sh:行1: g++: 未找到命令的错误问题在centos操作系统下面如何解决
  • java 连接 达梦数据库时报错 无法加载达梦数据库驱动: dm.jdbc.driver.DmDriver
  • 通过POSTMAN上传文件(入参IFromFile)
  • Biomu测试手册
  • 老车子ce导航 瑞风s5换大屏安卓导航
  • 老安卓机子延年益寿 更新webview和let x1根证书
  • 手把手玩转本地大模型:Ollama+DeepSeek+Dify 零门槛全流程指南
  • 6N90-ASEMI电源管理专用6N90
  • 七鲜小厨【京东外卖自营店】
  • apoc.export.graphml导出单个label进入恢复
  • 转载:python:导入不同路径下相同名称的模块
  • 渗透测试实战指南:企业网络安全防护的核心要素
  • Git
  • 【浙工大主办、IEEE出版】2025年智能控制与电气工程国际学术会议(IC-ICEE 2025)
  • Notepad++ 64bit手动安装JSONViewer插件
  • LCS
  • CTE查询数据量过大导致MySQL 8.0发生CORE问题解析
  • 浅析 manacher(马拉车)算法
  • NOIp2017 D1T2
  • Linux运行时so库的问题解决方案
  • HTML获取摄像头画面,拍照截图保存