65.9K
CodeProject 正在变化。 阅读更多。
Home

VB.NET 中 DataGridView 自定义标头

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.56/5 (15投票s)

2009年3月9日

CPOL

3分钟阅读

viewsIcon

189096

downloadIcon

8749

如何为您的 DataGridView 提供自定义标题

这是使用此代码将得到的内容的屏幕截图

DGVCustomHdr.gif

介绍 

此代码是 **Andy32** 的 自定义绘制 datagridviewcolumnheader(如 Excel 2007) 的细化版本。

通常,DataGridView 控件不允许您为其列标题设置背景图像。 此代码将以一种非常简单的方式实现这一点。

我这样做只是为了简化原始作者已经完成的工作。

我提供了一个图像,它是一个条纹(1 像素宽),用作背景。 您不需要更多,因为它将被拉伸以填充整个 columnheader
现在,由于它是一个半透明的 PNG,您将看到 Columheader 的颜色。 这样,您就不需要为要绘制标头的每种颜色提供不同的图像 - 只需更改 ColumnHeadersDefaultCellStyle.BackColor 属性即可。

我认为这再简单不过了。

背景

与原始文章一样,此代码说明了如何自定义绘制 DataGridView 列标题。

我的版本只是原始版本的优化版本,代码更少,并且进行了一些小的改进(前面提到的允许底层颜色透视的小尺寸透明图像)。

只有很少的代码:一个枚举(一组分组的常量),一个方法及其在 DataGridView 的事件中的调用。 仅此而已!!

哦,好吧,我忘记提及需要一些初始化代码(这里我直接在 Form 的 Load 事件处理程序中执行此操作,但您可以将其放入一个方法中并从 Load 事件中调用该方法)。

Private Sub frmMain_Load(ByVal sender As Object, ByVal e As EventArgs) _
 Handles Me.Load
	' Init.
	' Set up the Header Color and Font.
	With dgvData.ColumnHeadersDefaultCellStyle
		.Alignment = DataGridViewContentAlignment.MiddleCenter
		.BackColor = Color.DarkRed
		.ForeColor = Color.Gold
		.Font = New Font(.Font.FontFamily, .Font.Size, _
		 .Font.Style Or FontStyle.Bold, GraphicsUnit.Point)
	End With
	' Fill in some Text.
	For i As Int32 = 0 To 20
		Dim arrStrings As String()
		arrStrings = New String() _
		 { _
		 i.ToString, "Text " & i.ToString, i.ToString, _
		 "Text " & i.ToString, i.ToString _
		 }
		dgvData.Rows.Add(arrStrings)
		arrStrings = Nothing
	Next i
End Sub

只是为了将一些数据放入 DataGridView 并为其列标题设置 Color

使用方法  

DataGridViewCellPainting 事件中,调用提供的 GridDrawCustomHeaderColumns 方法(如果需要,可以随意缩短名称)

Private Sub dgvData_CellPainting(ByVal sender As Object, _
	ByVal e As DataGridViewCellPaintingEventArgs) _
	Handles dgvData.CellPainting
		' Only the Header Row (which Index is -1) is to be affected.
		If e.RowIndex = -1 Then
			GridDrawCustomHeaderColumns(dgvData, e, _
			 My.Resources.Button_Gray_Stripe_01_050, _
			 DGVHeaderImageAlignments.Stretch)
		End If
End Sub

上面的代码将使用我们方法中包含的代码覆盖正常的 CellPainting

Private Sub GridDrawCustomHeaderColumns(ByVal dgv As DataGridView, _
 ByVal e As DataGridViewCellPaintingEventArgs, ByVal img As Image, _
 ByVal Style As DGVHeaderImageAlignments)
	' All of the graphical Processing is done here.
	Dim gr As Graphics = e.Graphics
	' Fill the BackGround with the BackGroud Color of Headers.
	' This step is necessary, for transparent images, or what's behind
	' would be painted instead.
	gr.FillRectangle( _
	 New SolidBrush(dgv.ColumnHeadersDefaultCellStyle.BackColor), _
	 e.CellBounds)
	If img IsNot Nothing Then
		Select Case Style
			Case DGVHeaderImageAlignments.FillCell
				gr.DrawImage( _
				 img, e.CellBounds.X, e.CellBounds.Y, _
				 e.CellBounds.Width, e.CellBounds.Height)
			Case DGVHeaderImageAlignments.SingleCentered
				gr.DrawImage(img, _
				 ((e.CellBounds.Width - img.Width) \ 2) + _
							e.CellBounds.X, _
				 ((e.CellBounds.Height - img.Height) \ 2) + _
							e.CellBounds.Y, _
				 img.Width, img.Height)
			Case DGVHeaderImageAlignments.SingleLeft
				gr.DrawImage(img, e.CellBounds.X, _
				 ((e.CellBounds.Height - img.Height) \ 2) + _
							e.CellBounds.Y, _
				 img.Width, img.Height)
			Case DGVHeaderImageAlignments.SingleRight
				gr.DrawImage(img, _
				 (e.CellBounds.Width - img.Width) + _
							e.CellBounds.X, _
				 ((e.CellBounds.Height - img.Height) \ 2) + _
							e.CellBounds.Y, _
				 img.Width, img.Height)
			Case DGVHeaderImageAlignments.Tile
				' ***********************************************
				' To correct: It should display
				' just a stripe of images,
				' long as the whole header,
				' but centered in the header's
				' height.
				' This code WON'T WORK.
				' Any one got any better solution?
				'Dim rect As New Rectangle(e.CellBounds.X, _
				' ((e.CellBounds.Height - img.Height) \ 2), _
				' e.ClipBounds.Width, _
				' ((e.CellBounds.Height \ 2 + img.Height \ 2)))
				'Dim br As New TextureBrush_
				'(img, Drawing2D.WrapMode.Tile, _
				' rect)
				' ************************************************
				' This one works... but poorly
				' (the image is repeated
				' vertically, too).
				Dim br As New TextureBrush_
					(img, Drawing2D.WrapMode.Tile)
				gr.FillRectangle(br, e.ClipBounds)
			Case Else
				gr.DrawImage( _
				 img, e.CellBounds.X, e.CellBounds.Y, _
				 e.ClipBounds.Width, e.CellBounds.Height)
		End Select
	End If
	'e.PaintContent(e.CellBounds)
	If e.Value Is Nothing Then
		e.Handled = True
		Return
	End If
	Using sf As New StringFormat
		With sf
			Select Case dgv.ColumnHeadersDefaultCellStyle.Alignment
				Case DataGridViewContentAlignment.BottomCenter
					.Alignment = StringAlignment.Center
					.LineAlignment = StringAlignment.Far
				Case DataGridViewContentAlignment.BottomLeft
					.Alignment = StringAlignment.Near
					.LineAlignment = StringAlignment.Far
				Case DataGridViewContentAlignment.BottomRight
					.Alignment = StringAlignment.Far
					.LineAlignment = StringAlignment.Far
				Case DataGridViewContentAlignment.MiddleCenter
					.Alignment = StringAlignment.Center
					.LineAlignment = StringAlignment.Center
				Case DataGridViewContentAlignment.MiddleLeft
					.Alignment = StringAlignment.Near
					.LineAlignment = StringAlignment.Center
				Case DataGridViewContentAlignment.MiddleRight
					.Alignment = StringAlignment.Far
					.LineAlignment = StringAlignment.Center
				Case DataGridViewContentAlignment.TopCenter
					.Alignment = StringAlignment.Center
					.LineAlignment = StringAlignment.Near
				Case DataGridViewContentAlignment.TopLeft
					.Alignment = StringAlignment.Near
					.LineAlignment = StringAlignment.Near
				Case DataGridViewContentAlignment.TopRight
					.Alignment = StringAlignment.Far
					.LineAlignment = StringAlignment.Near
			End Select
			' This part could be handled...
			'Select Case dgv.ColumnHeadersDefaultCellStyle.WrapMode
			'	Case DataGridViewTriState.False
			'		.FormatFlags = StringFormatFlags.NoWrap
			'	Case DataGridViewTriState.NotSet
			'		.FormatFlags = StringFormatFlags.NoWrap
			'	Case DataGridViewTriState.True
			'		.FormatFlags = _
						StringFormatFlags.FitBlackBox
			'End Select
			.HotkeyPrefix = Drawing.Text.HotkeyPrefix.None
			.Trimming = StringTrimming.None
		End With
		With dgv.ColumnHeadersDefaultCellStyle
			gr.DrawString(e.Value.ToString, .Font, _
			 New SolidBrush(.ForeColor), e.CellBounds, sf)
		End With
	End Using
	e.Handled = True
End Sub

因此,它基本上是做什么的

绘制背景颜色,在其上叠加图像,绘制文本。

它对齐文本的方式与在任何其他控件上绘制文本的方式相同:检查用户希望如何对齐文本,并根据您将与 DrawString 方法结合使用的 StringFormat 对象进行操作。

有两个属性可以执行此操作:Alignment(水平方向)和 LineAlignment(垂直方向); 和三个值 Near(左侧或向上)、Far(右侧或向下)和 Center(中间)。

这些属性及其值的组合给出了文本的九种可能的对齐方式。

绘制图像的方式可能很棘手,所以...

...您会注意到在上面的代码中,有两个“所有星号”注释行分隔的部分。

那是改进的空间(当然是由于我对 DrawImage 方法的误解)。

我希望其他程序员会发现此代码根据他们的需要很有用。

让我知道您如何使这段代码更好。

历史

  • 2009 年 3 月 9 日:初始发布
© . All rights reserved.