转帖|其它|编辑:郝浩|2008-09-19 14:25:15.000|阅读 4510 次
概述:VS2005的DataGridView 多维合并标题 功能拓展
# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>
前几日,因为项目需要做一个可共用的控件类库。其中就需要DataGridView的合并表头功能。
在网上搜了一些资料,也下了一些自定义控件,观其效果离项目需要相去甚远。所以决定参考一下网上各位大大们的成果,自己做一个符合需要的DataGridView合并表头功能。
很多资料都是做2维的表头,其实基本上2维的合并标题就够用了,可惜我做的项目是MES相关的,需要多维的合并标题。思考了一番,决定导入树图(TreeView)的概念解决这个问题。
想法是这样:
想法很简单,但为了能够给使用者一个比较友好的使用接口,另一方面也是本人水平实在有限,颇费了一些时日,想起来真是汗颜啊。
上边的图或许可以给更直观的印象,图中Root节点是不予标题匹配的,而如果一个节点没有复数个的子节点它将显示为一个竖向合并的大标题(标题名称取回溯没有复数个字节点最上节点的文本(Root除外))。
代码如下:
Imports System
Imports System.ComponentModel
Imports System.Windows.Forms
Imports System.Drawing
Public Class HeaderUnitViewClass 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[SPAN]
<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 TreeView
Get
Return _columnTreeView(0)
End Get
End Property
Public ReadOnly Property NadirColumnList()Property NadirColumnList() As ArrayList
Get
If _columnTreeView Is Nothing Then
Return Nothing
End If
If _columnTreeView(0) Is Nothing Then
Return Nothing
End If
If _columnTreeView(0).Nodes Is Nothing Then
Return Nothing
End If
If _columnTreeView(0).Nodes.Count = 0 Then
Return Nothing
End If
_columnList.Clear()
GetNadirColumnNodes(_columnList _
, _columnTreeView(0).Nodes(0) _
, False)
Return _columnList
End Get
End Property
''' <summary>
''' 绘制合并表头
''' </summary>
''' <param name="node">合并表头节点</param>
''' <param name="e">绘图参数集</param>
''' <param name="level">结点深度</param>
''' <remarks></remarks>
Private Sub PaintUnitHeader()Sub PaintUnitHeader( _
ByVal node As TreeNode, _
ByVal e As System.Windows.Forms.DataGridViewCellPaintingEventArgs, _
ByVal level As Integer)
'根节点时退出递归调用
If level = 0 Then
Return
End If
'处理
Me.Update()
Dim uhRectangle As Rectangle
Dim uhWidth As Integer
Dim gridBrush As New SolidBrush(Me.GridColor)
Dim backColorBrush As New SolidBrush(e.CellStyle.BackColor)
Dim gridLinePen As New Pen(gridBrush)
Dim textFormat As New StringFormat()
textFormat.Alignment = StringAlignment.Center
uhWidth = GetUnitHeaderWidth(node)
If IsSingleChildNode(node) Then
uhRectangle = New Rectangle( _
e.CellBounds.Left, _
e.CellBounds.Top + (level - 1) * _cellHeight, _
uhWidth - 1, _
_cellHeight * (_columnDeep - level + 1) - 1)[SPAN]
Else
uhRectangle = New Rectangle( _
e.CellBounds.Left, _
e.CellBounds.Top + (level - 1) * _cellHeight, _
uhWidth - 1, _
_cellHeight - 1)
End If
e.Graphics.FillRectangle(backColorBrush, uhRectangle)
'划底线
e.Graphics.DrawLine(gridLinePen _
, uhRectangle.Left _
, uhRectangle.Bottom _
, uhRectangle.Right _
, uhRectangle.Bottom)
'划右端线
e.Graphics.DrawLine(gridLinePen _
, uhRectangle.Right _
, uhRectangle.Top _
, uhRectangle.Right _
, uhRectangle.Bottom)
'写字段文本
'e.Graphics.DrawString(node.Text _
' , Me.Font _
' , Brushes.Black _
' , uhRectangle _
' , textFormat)
e.Graphics.DrawString(node.Text _
, Me.Font _
, Brushes.Black _
, uhRectangle.Left + _
uhRectangle.Width / 2 - _
e.Graphics.MeasureString(node.Text, Me.Font).Width / 2 - 1 _
, uhRectangle.Top + _
uhRectangle.Height / 2 - _
e.Graphics.MeasureString(node.Text, Me.Font).Height / 2)
'递归调用()
If node.PrevNode Is Nothing Then
If Not node.Parent Is Nothing Then
PaintUnitHeader(node.Parent, e, level - 1)
End If
End If
End Sub
Private Function IsSingleChildNode()Function IsSingleChildNode( _
ByVal node As TreeNode) _
As Boolean
If node.Nodes Is Nothing Then
Return False
End If
If node.Nodes.Count = 0 Then
Return False
End If
If node.Nodes.Count = 1 Then
Return True
End If
Return False
End Function
''' <summary>
''' 获得合并标题字段的宽度
''' </summary>
''' <param name="node">字段节点</param>
''' <returns>字段宽度</returns>
''' <remarks></remarks>
Private Function GetUnitHeaderWidth()Function GetUnitHeaderWidth(ByVal node As TreeNode) As Integer[SPAN]
'获得非最底层字段的宽度
Dim uhWidth As Integer = 0
'获得最底层字段的宽度
If node.Nodes Is Nothing Then
Return Me.Columns(GetColumnListNodeIndex(node)).Width
End If
If node.Nodes.Count = 0 Then
Return Me.Columns(GetColumnListNodeIndex(node)).Width
End If
For i As Integer = 0 To node.Nodes.Count - 1
uhWidth = uhWidth + GetUnitHeaderWidth(node.Nodes(i))
Next
Return uhWidth
End Function
''' <summary>
''' 获得底层字段索引
''' </summary>
''' <param name="node">底层字段节点</param>
''' <returns>索引</returns>
''' <remarks></remarks>
Private Function GetColumnListNodeIndex()Function GetColumnListNodeIndex(ByVal node As TreeNode) As Integer
For i As Integer = 0 To _columnList.Count - 1
If CType(_columnList(i), TreeNode).Equals(node) Then
Return i
End If
Next
Return -1
End Function
''' <summary>
''' 获得底层字段集合
''' </summary>
''' <param name="alList">底层字段集合</param>
''' <param name="node">字段节点</param>
''' <param name="checked">向上搜索与否</param>
''' <remarks></remarks>
Private Sub GetNadirColumnNodes()Sub GetNadirColumnNodes( _
ByVal alList As ArrayList, _
ByVal node As TreeNode, _
ByVal checked As Boolean)
If checked = False Then
If node.FirstNode Is Nothing Then
alList.Add(node)
If Not node.NextNode Is Nothing Then
GetNadirColumnNodes(alList, node.NextNode, False)
Return
End If
If Not node.Parent Is Nothing Then
GetNadirColumnNodes(alList, node.Parent, True)
Return
End If[SPAN]
Else
If Not node.FirstNode Is Nothing Then
GetNadirColumnNodes(alList, node.FirstNode, False)
Return
End If
End If
Else
If node.FirstNode Is Nothing Then
Else
If Not node.NextNode Is Nothing Then
GetNadirColumnNodes(alList, node.NextNode, False)
Return
End If
If Not node.Parent Is Nothing Then
GetNadirColumnNodes(alList, node.Parent, True)
Return
End If
End If
End If
End Sub
''' <summary>
''' 单元格绘制(重写)
''' </summary>
''' <param name="e"></param>
''' <remarks></remarks>
Protected Overrides Sub OnCellPainting()Sub OnCellPainting( _
ByVal e As System.Windows.Forms.DataGridViewCellPaintingEventArgs)
'行标题不重写
If e.ColumnIndex < 0 Then
MyBase.OnCellPainting(e)
Return
End If
If _columnDeep = 1 Then
MyBase.OnCellPainting(e)
Return
End If
'绘制表头
If e.RowIndex = -1 Then
PaintUnitHeader(CType(NadirColumnList(e.ColumnIndex), TreeNode) _
, e _
, _columnDeep)
e.Handled = True
End If
End Sub
End Class
使用方法为:
使用注意:
自我使用评价:
本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com
文章转载自:CSDN