锐英源软件
第一信赖

精通

英语

开源

擅长

开发

培训

胸怀四海 

第一信赖

当前位置:锐英源 / 开源技术 / WPF / WPF树形DataGrid控件
服务方向
人工智能数据处理
人工智能培训
kaldi数据准备
小语种语音识别
语音识别标注
语音识别系统
语音识别转文字
kaldi开发技术服务
软件开发
运动控制卡上位机
机械加工软件
软件开发培训
Java 安卓移动开发
VC++
C#软件
汇编和破解
驱动开发
联系方式
固话:0371-63888850
手机:138-0381-0136
Q Q:396806883
微信:ryysoft

锐英源精品原创,禁止全文或局部转载,禁止任何形式的非法使用,侵权必究。点名“简易百科”和闲暇巴盗用锐英源原创内容。

WPF树形DataGrid控件


最近开发企业管理软件,WPF界面里安排了多个DataGrid显示数据,有些DataGrid有数据就是看不到,不知道界面上有哪些细节没处理好,也不好改,所以找了个树形DataGrid控件,里面的分组树形显示能满足我的要求,改改用于项目吧。本文来源于codeproject,看不懂codeproject,找锐英源软件。

 

介绍

本文介绍了一种使用内置WPF DataGrid创建TreeGrid、TreeListView或任何您想称之为它的方法。使用内置DataGrid有很多优点;然而,也存在一些缺点,即使用本文提出的方法的性能。

 

免责声明

本文旨在证明概念,而不是完全可部署/测试的解决方案。事实上,你会发现有很多函数被删除而没有实现。我认为它们对于概念的整体呈现是不必要的。此外,我的实现中很可能仍然存在bug。

 

出身背景

这些年过去了,微软还没有一个内置的WPF TreeGrid控件。说真的,到底是什么?可以在Codeproject和在线上找到许多尝试来创建TreeGrid控件,该控件可以以类似网格的方式显示分层数据。在做了这项研究之后,我在野外遇到的所有对照都比我认为的要有更多的缺点。

 

以下列出了在线控制的主要缺点:

 

控制重新发明车轮。这意味着控件是从头开始构建的,因此错过了主要功能。在我看来,要想成为一个完整的控件,它必须提供与DataGrid相同的所有功能集:选择、多选择、列、列大小调整、列隐藏、通过模板进行的大量定制等。遗憾的是,人们通常会为自己的特定用例构建这些控件,但由于时间的原因,无法实现DataGrid的整个功能集。

该控件使用现有控件的组合。例如,尝试使用智能控件模板将TreeView或ListView转换为TreeGrid。由于TreeView和ListView不是DataGrid…它们最终缺少DataGrid提供的大量定制功能。

UI虚拟化。以上所有方法都不能很好地与UI虚拟化配合使用。如果您添加了大量项,那么视图控件项实际上是在后台创建的。我之前实际上尝试过在没有虚拟化的情况下向DataGrid添加项,并允许它为每个数据项创建一个包含所有子控件的DataGrid行。在我的32位进程耗尽内存之前,我已经创建了100000个项目,创建所有这些项目花费了“分钟”。DataGrid行也没有复杂的控件层次结构。

我查看了许多专业的第三方控件,如XCeed WPF DataGrid。这个DataGrid似乎有一个分层的特性,我认为称为主视图或其他东西;但是,主视图功能要求您为升级版本付费。我遇到的唯一一个来自专业公司的免费控件是syncfusion TreeGrid控件。我对它们进行了测试,虽然它们有效,但由于一些问题,我决定不使用它们。第一个问题是,我不得不安装他们的“工作室”垃圾(这是一个大安装)来访问我正在寻找的DLL,这让我非常恼火。第二,一旦我开始在代码中使用控件,它们就好像被黑到了一起。就像我说的,这些控件起作用了,只是代码中的味道很难闻。我发现的任何其他第三方控件都不是免费的。

 

因此,如上所述,如果我们能够以一种半有效的方式重用DataGrid来创建TreeGrid,那不是很好吗?它是一个非常复杂的控件,内置了对UI虚拟化、选择、列和模板的支持。

 

还有另一种尝试使用我在网上遇到的DataGrid创建TreeGrid的策略。DataGrid有一个分组的概念,您可以将子DataGrid嵌套在一个组中,以创建类似树的效果。我向你保证,这不是本文将要介绍的内容。这种方法有很多问题,主要的问题是它无法扩展。如果你有一个树节点的深层结构呢?每个树节点都必须有自己的DataGrid。

 

缺点

在本文中,我将从这种方法的主要缺点开始,这样您就可以提前了解您将得到什么。以我将介绍的方式使用DataGrid并不是DataGrid的设计者打算如何使用它。因此,由于内部WPF实现,存在一些性能问题。

 

预先加载许多“根”树元素和许多最初处于“扩展”状态的子元素需要一段时间。

经过一些基本的性能测试后,大约10000个项目可以在初始化时加载,而不会出现时间延迟。别逼我打那个号码。

树中大约有100000个项目处于打开或展开状态,允许节点展开或折叠,而不会出现太多时间延迟。别逼我打那个号码。

 

优势

因此,考虑到上述缺点,我敢打赌,与不支持UI虚拟化的被黑客攻击的TreeView或ListView相比,此实现仍将获得更好的结果。所以……如果你有一个数据集,是“排序小”排序不,我认为这个解决方案会起作用。我的用例完全符合这个描述。不用去对WPF团队大喊大叫来解决一些内部实现问题,这就是我们必须解决的问题。

 

该解决方案为您提供了DataGrid控件“减去”DataGrid分组功能的强大功能。我相信你可以找到一种使用分组功能的方法,我不知道……但是在TreeGrid中显示分层数据有点否定了在DataGrid中使用分组功能。

由于使用DataGrid,UI虚拟化。

支持延迟加载树项。

AlternationCount有效。如果您查看顶部的屏幕截图或运行上面的演示,您会注意到交替计数有效。曾经尝试过在TreeView控件上设置交替计数吗?TreeView中的某些项将无法根据它们在树层次结构中的位置获得正确的索引。Treeview项在父Treeview中没有总体布局的概念,因此Treeview所能做的最好的事情就是在此处或那里重置索引。

实施

不用再多说了,让我们来讨论如何欺骗DataGrid来显示树层次结构。让我们来看看这里的问题。树结构或模型通常在底部有根,每个根可以有一组递归的子级。DataGrid控件没有层次结构的概念,它只想显示项列表。因此,是否可以将树层次结构转换为项目列表;物品的平面清单?

 

上一个问题的答案是肯定的。这称为展平模型。在我的实现中,扁平树层次结构被称为“扁平模型”。

 

下面是它的工作原理。我的实现始于所谓的TreeGridModel。TreeGridModel允许向其中添加根树元素。每个树元素可以有一组递归的子元素。无论何时向父树元素添加根或子元素,TreeGridModel都会使用内部方法进行通知。然后,TreeGridModel基于事件构建了所谓的TreeGrid FlatModel。

 

当TreeGridElement展开或折叠时,TreeGrid模型会再次得到通知,并相应地更新TreeGridsFlatModel。

 

模型的主要组成部分总结如下:

 

TreeGridElement:公开可以从DataGrid绑定到的几个依赖属性。最重要的属性是IsExpanded属性。当此更改时,将通知TreeGridModel,以便它可以更新TreeGrid FlatModel。TreeGridElement还管理一些内部属性,如层次结构中的父级和层次结构中级别。元素的Level属性可用于实现列中的间距。

TreeGridModel:该模型允许向其中添加根TreeGrid元素。所有根都“显示”或添加到TreeGridFlatModel,但可能未处于显示子元素的展开状态。模型在处理来自子TreeGridElements或模型本身的各种事件时更新TreeGrid FlatModel。

TreeGridFlatModel:这只是一个可观察集合的包装,用于实现一些内部方法。值得注意的是,这可以从DataGrid绑定到;但是,用户不能修改它,因为它是TreeGridModel用来生成扁平树层次结构的内部集合。

因此,与其解释如何从分层树模型中生成扁平模型,不如自己去探索并逐步完成代码。请记住,上面的演示只实现了添加、扩展和折叠功能,用于概念验证。此外,我想指出的是,这是我对如何从层次结构中生成扁平模型的“我的”实现,可能还有十亿个更有效的模型。

 

表演

我想保持这一部分的简短。本质上,我从分层模型生成平面模型的实现在很大程度上依赖于集合范围函数。可观察集合中缺少的一件事是什么?-范围功能。展开或折叠项时,需要在FlatModel中添加或删除一系列子项,并且由于WPF实现,此操作无法进行批处理。这使得它非常无性能。对WPF团队大喊大叫,因为他们认为没有人会想要可观察集合中的范围函数。

 

笔记

您可以固有地将范围函数添加到可观察的集合中,甚至可以实现自己的集合。当WPF ItemsControl绑定到实现INotifyCollectionChanged的集合时,问题就会出现。如果您的事件一次通过集合中添加或删除的多个项,则会得到一个很好的异常:“不支持范围操作。”

 

用法

要使用TreeGridModel,基本上必须创建它,然后可以使用DataGrid的ItemsSource属性将公共属性FlatModel绑定到它。完成此操作后,可以通过添加、展开或折叠节点来修改层次结构。

 

TreeGridElement用作用户要实现的具体TreeGrid项的基类。这意味着要创建自己的项,您可以从TreeGridElement派生并开始添加可以使用DataGrid绑定到的字段。要实现延迟加载,可以使用IsExpanding事件将子级加载到节点中。还有一个名为“HasChildren”的属性,可以绑定为显示或隐藏每个节点的小切换按钮。

 

在演示中,我创建了一个DataGrid,其中第一列是模板列。然后,我创建了想要如何在单元格中显示节点的布局。第一列中的每个单元格都有一个包含3列的网格。第一列用于添加空白,以便根据项的Level属性正确定位TreeItem子切换按钮。第二列用于显示TreeItem子切换按钮。这里,我只使用一个复选框,因为它是一个简单的切换按钮;但是,您可以创建一个箭头。第三列用于通过绑定到name属性来显示项的名称。

友情链接
版权所有 Copyright(c)2004-2021 锐英源软件
公司注册号:410105000449586 豫ICP备08007559号 最佳分辨率 1024*768
地址:郑州大学北校区院(文化路97号院)内