(原创文章,转载请注明来源:http://blog.csdn.net/hulihui)
今年假期较长,用Delphi完成一个单机分布式报表系统后,一直在思考问题:去年开始,交通运输部下发的软件全部转到.NET。偶是否也要如此?多年经验体会,具有Delphi三个组件:多层表头表格组件(TDBGridEh)、字符表格组件(TAdvStringGrid)、文件压缩组件(THBackup),就可以满足自己的技术需求。搜索.NET的相关资源结果:免费.NET多层表头组件功能太弱,字符表格组件可用DataGridView代替,压缩则可以用.NET的TGZipStream实现。
思考与技术比较的结果是:虽然Delphi2009刚发布,但个人感到C#语法优美、VS人性化好、编程效率高,具有底层平台支持,还有免费Express版本(无版权纠纷)。于是,考虑自己做.NET压缩组件和表格组件,一来学习C#可视化编程技术,二来为今后作技术准备。
多层表头的主要技术问题是:第一,表示与存储多层表头;第二,绘制多表头列与合并列。
针对第一个问题,网上搜索资料看,存储与表示多层表头有多种方案,偶考虑如下两种:
第二个技术难点就是表头绘制了。网上相关的技术文章多,关键是重载DataGridView的绘制方法OnCellPaint,把表头作为 一个大的长方形,一层层、一格格地绘制。实现时要注意,不仅仅是绘制当前列的表头,还需要绘制左边和右边部分(合并报表头时)。此外,如果当前列是排序的,还需要绘制排序三角型符号。
原本做出多层表头就收手。但根据经验,用表格处理数据显示列的合计数,将十分方便数据录入者校对,并且TDBGridEh就具有该功能。于是,就想一鼓作气添加合计行。呵呵,不做不知道,就这个功能,占用了偶大部分的时间和代码量。实现过程中碰到的技术问题有:
既然做出了多层表头、合计行,就想做出像Excel样显示行号、像TAdvStringGrid样设置行或单元的背景色。比较而言,这两个技术实现容易多了。其中,行或单元背景采取用事件完成窗体和表格的消息交互,这也是TAdvStringGrid的实现方案。此外,TDataGridViewEx还实现了列排序后当前行重定位、垂直滚动条顶/底端点击时移动到行首/行末,列数据为0时显示空白(由单元格组件TDataGridViewTextBoxCellEx中的GetFormattedValue方法实现),等等。
暂时不打算将TDataGridViewEx做成Freeware,这里就不具体贴出代码了,感兴趣的读者可以留言相互探讨。下面是组件的Demo图,下载资源见本站: 带合计行的多层表头组件TDataGridViewEx演示程序。
今天正式开学了。回顾这个假期,忙碌了50多天。期间,用Delphi完成了一个交通运输部数据采集系统的补充软件,用C#完成了三个实用组件:表格组件(TDataGridViewEx)、压缩组件(TGZipCompressBar)、进度条组件(TProgressBar),还在CSDN上撰写了三篇文章。其中,TDataGridViewEx技术难度最大,耗费了偶3周多时间,代码则超过3000行,而整个假期的总代码量超过20000行(部分Copy原Delphi程序)。做出实际东西,既要求自己去思考问题,又学到许多C#可视化编程技术,如:组件实现技术、事件实现机制、图形绘制等,一举多得。但对于MS可视化编程,偶还有觉得许多的东西都靠自己一点点的摸索,书本或网上资源过少。
技术之路漫漫修远,只有紧随、努力与探索,特别是我们60后的程序员。
思考与技术比较的结果是:虽然Delphi2009刚发布,但个人感到C#语法优美、VS人性化好、编程效率高,具有底层平台支持,还有免费Express版本(无版权纠纷)。于是,考虑自己做.NET压缩组件和表格组件,一来学习C#可视化编程技术,二来为今后作技术准备。
多层表头的主要技术问题是:第一,表示与存储多层表头;第二,绘制多表头列与合并列。
针对第一个问题,网上搜索资料看,存储与表示多层表头有多种方案,偶考虑如下两种:
- 用TreeView组件表示与存储。符合实际的层次结构,容易理解。但实现需要递归,效率不高,还要独立存储对象;
- 用类似TDBGridEh的表示方法,即用Col1|11、Col1|12形式。实现时用Column对象的HeaderText存储。
第二个技术难点就是表头绘制了。网上相关的技术文章多,关键是重载DataGridView的绘制方法OnCellPaint,把表头作为 一个大的长方形,一层层、一格格地绘制。实现时要注意,不仅仅是绘制当前列的表头,还需要绘制左边和右边部分(合并报表头时)。此外,如果当前列是排序的,还需要绘制排序三角型符号。
原本做出多层表头就收手。但根据经验,用表格处理数据显示列的合计数,将十分方便数据录入者校对,并且TDBGridEh就具有该功能。于是,就想一鼓作气添加合计行。呵呵,不做不知道,就这个功能,占用了偶大部分的时间和代码量。实现过程中碰到的技术问题有:
- 合计数存储问题。用一个数组存储?那么列删除、隐藏或增加时要同步。经过思考,就把数据存储在列对象中,但需要定制自己的列类型TDataGridViewTextBoxColumnEx(继承自DataGridViewTextBoxColumn)。
- 数据变化时列合计问题。修改单元格时,要重算全部列?还是用单元格保存一个转换后的数据?多方考虑,偶定制了自己的单元格TDataGridViewTextBoxCellEx,增加了一个数据型字段,并添加到定指列中。
- 数据源变化时合计问题。这个问题比较复杂,因为数据绑定的底层机制不清楚,只能假设数据源实现了IBindingList接口,依靠其ListChanged事件捕获数据变化,再合计变化的列或行。
- 合计效率问题。如果能捕获数据变化的单元格,那么只需要进行一个加/减操作即可得到当前列的合计。但编程实现的单元格数据变化,程序实现的绑定源行数据变化,必须扫描全部的变化单元格。特别,绑定源行数据变化时,有时必须重算整个表格。另外,数据排序后、绑定源变化时,也必须重算整个表格。
- 表头绘制问题。原先的表头绘制只有2个函数,现在必须增加到6个函数,需要考虑是否是多层表头、左上方方块绘制、合计行的数据格式,等等。
- 合计行位置问题。一般如TDBGridEh,将合计行置于表格底部。实际报表中,合计行在表格顶部很多,TDataGridViewEx已经绘制了多层表头,在增加一个合计行,技术上容易实现。
既然做出了多层表头、合计行,就想做出像Excel样显示行号、像TAdvStringGrid样设置行或单元的背景色。比较而言,这两个技术实现容易多了。其中,行或单元背景采取用事件完成窗体和表格的消息交互,这也是TAdvStringGrid的实现方案。此外,TDataGridViewEx还实现了列排序后当前行重定位、垂直滚动条顶/底端点击时移动到行首/行末,列数据为0时显示空白(由单元格组件TDataGridViewTextBoxCellEx中的GetFormattedValue方法实现),等等。
暂时不打算将TDataGridViewEx做成Freeware,这里就不具体贴出代码了,感兴趣的读者可以留言相互探讨。下面是组件的Demo图,下载资源见本站: 带合计行的多层表头组件TDataGridViewEx演示程序。
今天正式开学了。回顾这个假期,忙碌了50多天。期间,用Delphi完成了一个交通运输部数据采集系统的补充软件,用C#完成了三个实用组件:表格组件(TDataGridViewEx)、压缩组件(TGZipCompressBar)、进度条组件(TProgressBar),还在CSDN上撰写了三篇文章。其中,TDataGridViewEx技术难度最大,耗费了偶3周多时间,代码则超过3000行,而整个假期的总代码量超过20000行(部分Copy原Delphi程序)。做出实际东西,既要求自己去思考问题,又学到许多C#可视化编程技术,如:组件实现技术、事件实现机制、图形绘制等,一举多得。但对于MS可视化编程,偶还有觉得许多的东西都靠自己一点点的摸索,书本或网上资源过少。
技术之路漫漫修远,只有紧随、努力与探索,特别是我们60后的程序员。
2008年9月1日晚修改,9月2日再改
本文介绍了使用Delphi和.NET的C#实现带合计行的多层表头组件TDataGridViewEx的过程。通过自定义列类型TDataGridViewTextBoxColumnEx和单元格TDataGridViewTextBoxCellEx,解决数据存储、变化时的合计计算问题。同时,针对数据源变化、排序及绑定源行变化时的合计效率进行了优化。表头绘制和合计行位置设计也是讨论的重点。
1022

被折叠的 条评论
为什么被折叠?



