实现WinFormsDataGridView的多级表头功能
作者:幸福---wang | 来源:互联网 | 2024-11-29 11:38
本文介绍了如何在WinForms的DataGridView控件中实现多级表头,以满足复杂数据展示的需求。通过自定义绘制技术,我们可以在DataGridView中实现类似Web表格的多级表头效果。
最近我们在一个 B/S 系统中增加了智能客户端的功能,智能客户端提供了更加丰富的用户体验和操作便捷性。然而,在使用 WinForms 开发过程中,我们遇到了一些挑战,特别是 DataGridView 控件的功能限制。与 Web 开发相比,WinForms 的控件在某些方面显得不够强大,例如 DataGridView 不支持多级表头和表尾合计功能。 对于企业级应用,如 MIS 系统,多级表头是不可或缺的功能,客户对此有明确的需求。为了满足这一需求,我们尝试了多种解决方案,包括使用 COM 控件 FlexGrid 和开源项目 SourceGrid3,但这些方案都存在不同程度的问题。最终,我们决定对 DataGridView 进行自定义扩展,以实现多级表头功能。 ### 实现步骤 1. **继承 DataGridView** 首先,我们需要创建一个继承自 DataGridView 的新类,以便添加自定义的多级表头功能。 2. **重写 CellPainting 事件** 在 CellPainting 事件中,我们可以自定义绘制逻辑来实现多级表头。具体代码如下: ```csharp private void DataGridViewEx_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) { if (e.RowIndex == -1) { Rectangle newRect = new Rectangle(e.CellBounds.X + 1, e.CellBounds.Y + 1, e.CellBounds.Width - 4, e.CellBounds.Height - 4); using (Brush gridBrush = new SolidBrush(this.GridColor), backColorBrush = new SolidBrush(e.CellStyle.BackColor)) { using (Pen gridLinePen = new Pen(gridBrush)) { e.Graphics.FillRectangle(backColorBrush, e.CellBounds); e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left, e.CellBounds.Bottom - 1, e.CellBounds.Right - 1, e.CellBounds.Bottom - 1); if (e.ColumnIndex > -1 && topRow != null && topRow.Cells[e.ColumnIndex].ColSpan > 1) { e.Graphics.DrawLine(gridLinePen, e.CellBounds.Right - 1, e.CellBounds.Top + e.ClipBounds.Height / 2, e.CellBounds.Right - 1, e.CellBounds.Bottom); } else { e.Graphics.DrawLine(gridLinePen, e.CellBounds.Right - 1, e.CellBounds.Top, e.CellBounds.Right - 1, e.CellBounds.Bottom); } int scale = e.CellBounds.Height / 3; if (e.ColumnIndex > -1 && topRow.Cells[e.ColumnIndex].Text != null) { scale = e.CellBounds.Height / 2; e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left, e.CellBounds.Bottom - e.CellBounds.Height / 2, e.CellBounds.Right, e.CellBounds.Bottom - e.CellBounds.Height / 2); } if (e.Value != null) { e.Graphics.DrawString(e.Value.ToString(), e.CellStyle.Font, Brushes.Crimson, e.CellBounds.X + 2, e.CellBounds.Y + scale + 2, StringFormat.GenericDefault); } if (e.ColumnIndex > -1 && topRow.Cells[e.ColumnIndex].RelateIndex > -1 && topRow.Cells[e.ColumnIndex].Text != null) { Rectangle recCell = new Rectangle(e.CellBounds.X - 1 - topRow.Cells[e.ColumnIndex].SpanRowWith, e.CellBounds.Y + 1, topRow.Cells[e.ColumnIndex].SpanRowWith, e.CellBounds.Height / 2); StringFormat sf = new StringFormat(); sf.Alignment = StringAlignment.Center; e.Graphics.DrawString(topRow.Cells[e.ColumnIndex].Text, e.CellStyle.Font, Brushes.Crimson, recCell, sf); } e.Handled = true; } } } } ``` 3. **调用方法** 在实际使用中,可以通过以下代码设置多级表头: ```csharp dataGridViewEx1.TopRow.Cells[2].Text = "入库"; dataGridViewEx1.TopRow.Cells[2].ColSpan = 2; dataGridViewEx1.TopRow.Cells[4].Text = "出库"; dataGridViewEx1.TopRow.Cells[4].ColSpan = 2; ``` ### 效果图 ![效果图](https://img1.php1.cn/3cd4a/24cea/2be/309b316484c79626.jpeg) 除了多级表头,我们还实现了表尾合计功能,基本满足了客户的需求。希望这篇文章能帮助到有类似需求的开发者,减少他们在实现多级表头时的弯路。
推荐阅读
本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ...
[详细]
蜡笔小新 2024-12-28 09:46:23
本文详细解析了 DotNetNuke (DNN) 的两种主要版本:Community 和 Professional。通过对比两者的功能和附加组件,帮助用户选择最适合其需求的版本。 ...
[详细]
蜡笔小新 2024-12-27 13:14:08
本文详细介绍了Java中org.eclipse.ui.forms.widgets.ExpandableComposite类的addExpansionListener()方法,并提供了多个实际代码示例,帮助开发者更好地理解和使用该方法。这些示例来源于多个知名开源项目,具有很高的参考价值。 ...
[详细]
蜡笔小新 2024-12-27 16:11:49
本文详细介绍了Akka中的BackoffSupervisor机制,探讨其在处理持久化失败和Actor重启时的应用。通过具体示例,展示了如何配置和使用BackoffSupervisor以实现更细粒度的异常处理。 ...
[详细]
蜡笔小新 2024-12-27 15:04:09
本文详细介绍了Java中org.neo4j.helpers.collection.Iterators.single()方法的功能、使用场景及代码示例,帮助开发者更好地理解和应用该方法。 ...
[详细]
蜡笔小新 2024-12-28 10:51:55
本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ...
[详细]
蜡笔小新 2024-12-28 10:36:30
Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ...
[详细]
蜡笔小新 2024-12-28 08:54:34
在前两篇文章中,我们探讨了 ControllerDescriptor 和 ActionDescriptor 这两个描述对象,分别对应控制器和操作方法。本文将基于 MVC3 源码进一步分析 ParameterDescriptor,即用于描述 Action 方法参数的对象,并详细介绍其工作原理。 ...
[详细]
蜡笔小新 2024-12-27 15:26:10
本文详细介绍了如何构建一个高效的UI管理系统,集中处理UI页面的打开、关闭、层级管理和页面跳转等问题。通过UIManager统一管理外部切换逻辑,实现功能逻辑分散化和代码复用,支持多人协作开发。 ...
[详细]
蜡笔小新 2024-12-27 10:28:40
本文介绍如何使用阿里云的fastjson库解析包含时间戳、IP地址和参数等信息的JSON格式文本,并进行数据处理和保存。 ...
[详细]
蜡笔小新 2024-12-26 16:06:09
本文探讨了在ASP.NET MVC框架中,如何通过Area机制有效地组织和管理大规模应用程序的不同功能模块。通过合理的文件夹结构和命名规则,开发人员可以更高效地管理和扩展项目。 ...
[详细]
蜡笔小新 2024-12-25 22:53:48
探讨如何真正掌握Java EE,包括所需技能、工具和实践经验。资深软件教学总监李刚分享了对毕业生简历中常见问题的看法,并提供了详尽的标准。 ...
[详细]
蜡笔小新 2024-12-25 13:38:29
小编给大家分享一下实用正则表达式有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下 ...
[详细]
蜡笔小新 2024-12-22 13:59:04
本文介绍了在Windows环境下使用pydoc工具的方法,并详细解释了如何通过命令行和浏览器查看Python内置函数的文档。此外,还提供了关于raw_input和open函数的具体用法和功能说明。 ...
[详细]
蜡笔小新 2024-12-26 17:05:56
最新发布的 libsodium 1.0.15 版本带来了若干不兼容的变更,其中包括默认密码散列算法的更改和其他重要调整。 ...
[详细]
蜡笔小新 2024-12-26 11:03:58