前几日,因为项目需要做一个可共用的控件类库。其中就需要DataGridView的合并表头功能。
在网上搜了一些资料,也下了一些自定义控件,观其效果离项目需要相去甚远。所以决定参考一下网上各位大大们的成果,自己做一个符合需要的DataGridView合并表头功能。
很多资料都是做2维的表头,其实基本上2维的合并标题就够用了,可惜我做的项目是MES相关的,需要多维的合并标题。思考了一番,决定导入树图(TreeView)的概念解决这个问题。
想法是这样:
1。在多维标题中每一个最底层的标题相当于Tree中的最低深度的节点。而且这个Tree中有一个Root节点, 而且只有Root节点不予多维标题中的标题相匹配。
2。当前标题上面的合并标题相当于Tree中与当前节点的Parent节点,标题名称与节点名称相匹配。
3。当前标题的宽度为与之匹配的Tree节点的所有Children节点的宽度之和。
4。从最底层节点开始绘起,当当前节点没有前驱节点时(firstnode),向上搜索继续绘制其父节点,
依次递归,否则该节点只绘制自己完事。
5。如果当前节点只有一个子节点则竖向合并掉子节点区域进行重绘。
想法很简单,但为了能够给使用者一个比较友好的使用接口,另一方面也是本人水平实在有限,颇费了一些时日,想起来真是汗颜啊。
上边的图或许可以给更直观的印象,图中Root节点是不予标题匹配的,而如果一个节点没有复数个的子节点它将显示为一个竖向合并的大标题(标题名称取回溯没有复数个字节点最上节点的文本(Root除外))。
代码如下:
Imports System.ComponentModel
Imports System.Windows.Forms
Imports System.Drawing
Public Class HeaderUnitView Class HeaderUnitView
Inherits DataGridView
Private _columnTreeView() As TreeView
Private _columnList As New ArrayList
Private _cellHeight As Integer = 25
Private _columnDeep As Integer = 1
<Description("设置或获得合并表头树的深度")> _
Public Property ColumnDeep()Property ColumnDeep() As Integer
Get
If Me.Columns.Count = 0 Then
_columnDeep = 1
End If
Me.ColumnHeadersHeight = _cellHeight * _columnDeep
Return _columnDeep
End Get
Set(ByVal value As Integer)
If value < 1 Then
_columnDeep = 1
Else
_columnDeep = value
End If
Me.ColumnHeadersHeight = _cellHeight * _columnDeep
End Set
End Property
<Description("添加合并式单元格绘制的所需要的节点对象")> _
Public Property ColumnTreeView()Property ColumnTreeView() As TreeView()
Get
Return _columnTreeView
End Get
Set(ByVal value As TreeView())
If Not _columnTreeView Is Nothing Then
For i As Integer = 0 To _columnTreeView.Length - 1
_columnTreeView(i).Dispose()
Next
End If
_columnTreeView = value
End Set
End Property
<Description("设置添加的字段树的相关属性")> _
Public ReadOnly Property ColumnTreeViewNode()Property ColumnTreeViewNode() As