在VB.NET中,经常需要在DataGridView中展示数据的进度或百分比,以便用户可以直观地比较各行数据。本文将介绍一种方法,通过调用一个共享类方法来实现在DataGridView的特定列中绘制进度条,这种方法可以很容易地集成到任何DataGridView中。
本项目以简单的方式展示了如何实现截图中的网格功能。根据是否显示目标指示器(由CheckBox1的状态决定),可以调用以下方法:
以下是一个处理DataGridView的CellPainting事件的代码示例:
Private Sub DataGridView1_CellPainting(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles DataGridView1.CellPainting
' 避免绘制超出数据区域的行或列
If e.RowIndex < 0 OrElse e.ColumnIndex < 0 Then Exit Sub
' 检查是否正在绘制百分比列
If e.ColumnIndex <> Columns.Percent Then Exit Sub
' 获取数据行
Dim oRow As DataSet1.DataRow = DirectCast(DataGridView1.Rows(e.RowIndex).DataBoundItem, DataRowView).Row
' 告诉DataGridView将处理绘制单元格
e.Handled = True
' 根据百分比值选择条形颜色
Dim oColor As Drawing.Color = Color.Green
If CheckBox1.Checked AndAlso oRow.percent < _ciTarget Then
oColor = Color.Red
End If
' 绘制带有条形的单元格
If CheckBox1.Checked Then
Bar.PintaDegradado(oColor, e, oRow.percent, _ciTarget, Color.Orange)
Else
Bar.PintaDegradado(oColor, e, oRow.percent)
End If
End Sub
以下是Bar类代码,用于绘制DataGridView单元格中的条形:
Public Class Bar
Public Shared Sub PintaDegradado(ByVal oColor As Drawing.Color, ByVal e As DataGridViewCellPaintingEventArgs)
Bar.PintaDegradado(oColor, e, -1)
End Sub
Public Shared Sub PintaDegradado(ByVal oColor As Drawing.Color, ByVal e As DataGridViewCellPaintingEventArgs, ByVal iPorcentaje As Integer)
Dim aCol As Drawing.Color() = {oColor}
Dim aPor As Integer() = {iPorcentaje}
If iPorcentaje = -1 Then
Dim aPorN As Integer() = {}
Bar.PintaDegradado(aCol, e, aPorN)
Else
Bar.PintaDegradado(aCol, e, aPor)
End If
End Sub
Public Shared Sub PintaDegradado(ByVal oColor As Drawing.Color, ByVal e As DataGridViewCellPaintingEventArgs, ByVal iPorcentaje As Integer, ByVal iObjetivo As Integer, ByVal oColorObjetivo As Drawing.Color)
Dim aCol As Drawing.Color() = {oColor, oColorObjetivo}
Dim aPor As Integer() = {iPorcentaje, iObjetivo}
Bar.PintaDegradado(aCol, e, aPor)
End Sub
Private Shared Sub PintaDegradado(ByVal aColores As Drawing.Color(), ByVal e As DataGridViewCellPaintingEventArgs, ByVal aPorcentajes As Integer())
' 声明画刷和颜色数组
Dim oPin1 As Drawing2D.LinearGradientBrush = Nothing
Dim oPin2 As Drawing2D.LinearGradientBrush = Nothing
Dim oPinO As Drawing2D.LinearGradientBrush = Nothing
Dim oColor As Drawing.Color = aColores(0)
' 处理任何异常
Try
' 获取单元格矩形
Dim oCelda As New Rectangle(e.CellBounds.X - 1, e.CellBounds.Y - 1, e.CellBounds.Width, e.CellBounds.Height)
' 调试百分比数组
For iC As Integer = 0 To aPorcentajes.Length - 1
If aPorcentajes(iC) > 100 Then aPorcentajes(iC) = 100
Next
' 声明矩形。
Dim oRect1 As Rectangle
Dim oRect2 As Rectangle
Dim oObj As Rectangle
Dim oFond As Rectangle
Dim oCuad As Rectangle = Nothing
Dim oBorder As Rectangle
' 声明百分比变量
Dim iPorcentaje As Integer = 0
Dim bPor As Boolean = False
' 检测是否传递了百分比
If aPorcentajes.Length > 0 Then
bPor = True
iPorcentaje = aPorcentajes(0)
If iPorcentaje > 0 Then
' 获取矩形和画刷以显示百分比指示器。
oRect1 = New Rectangle(oCelda.X + 4, oCelda.Y + 4, Math.Round(((oCelda.Width - 7) * iPorcentaje * 0.01) + 0.49), Math.Round((oCelda.Height - 8) / 2))
If oRect1.Width > oCelda.Width - 7 Then oRect1.Width = oCelda.Width - 7
oRect2 = New Rectangle(oCelda.X + 4, oRect1.Bottom - 1, oRect1.Width, (oCelda.Height - 6) - oRect1.Height)
oFond = New Rectangle(oCelda.X + 4, oCelda.Y + 4, oCelda.Width - 7, oCelda.Height - 7)
oPin1 = New Drawing2D.LinearGradientBrush(oRect1, Color.White, Color.FromArgb(180, oColor), Drawing2D.LinearGradientMode.Vertical)
oPin2 = New Drawing2D.LinearGradientBrush(oRect2, oColor, Color.FromArgb(70, oColor), Drawing2D.LinearGradientMode.Vertical)
End If
If aPorcentajes.Length > 1 Then
' 获取矩形和画刷以显示目标指示器
Dim iObj As Integer = aPorcentajes(1)
Dim iPos As Integer = oCelda.X + 4 + Math.Round(((oCelda.Width - 7) * iObj * 0.01) + 0.49)
Dim iIni As Integer = iPos - 20
If iIni < oCelda.X + 4 Then iIni = oCelda.X + 4
oObj = New Rectangle(iIni, oCelda.Y + 2, iPos - iIni, oCelda.Height - 4)
oPinO = New Drawing2D.LinearGradientBrush(oObj, Drawing.Color.FromArgb(0, aColores(1)), aColores(1), Drawing2D.LinearGradientMode.Horizontal)
End If
End If
' 获取边框矩形
oCuad = New Rectangle(oCelda.X + 3, oCelda.Y + 3, oCelda.Width - 6, oCelda.Height - 6)
Else
' 获取矩形和画刷以填充单元格(没有百分比)
oRect1 = New Rectangle(oCelda.X + 1, oCelda.Y + 1, oCelda.Width - 1, Math.Round(oCelda.Height / 2))
oRect2 = New Rectangle(oCelda.X + 1, oRect1.Bottom - 1, oCelda.Width - 1, oCelda.Height - oRect1.Height)
oFond = New Rectangle(oCelda.X + 1, oCelda.Y + 1, oCelda.Width - 1, oCelda.Height)
oPin1 = New Drawing2D.LinearGradientBrush(oRect1, Color.White, Color.FromArgb(180, oColor), Drawing2D.LinearGradientMode.Vertical)
oPin2 = New Drawing2D.LinearGradientBrush(oRect2, oColor, Color.FromArgb(70, oColor), Drawing2D.LinearGradientMode.Vertical)
End If
' 绘制单元格背景
e.PaintBackground(e.CellBounds, True)
If bPor Then e.Graphics.DrawRectangle(Pens.DimGray, oCuad) End If
' 绘制玻璃条
If oPin1 IsNot Nothing Then
e.Graphics.FillRectangle(Brushes.White, oFond)
e.Graphics.FillRectangle(oPin1, oRect1)
e.Graphics.FillRectangle(oPin2, oRect2)
End If
' 绘制目标指示器
If oPinO IsNot Nothing Then
e.Graphics.FillRectangle(oPinO, oObj)
End If
' 绘制单元格内容
e.PaintContent(oCelda)
e.Paint(oCelda, DataGridViewPaintParts.Border)
e.Handled = True
Catch ex As Exception
Debug.Print(ex.Message)
Finally
' 释放所有资源
If oPin1 IsNot Nothing Then oPin1.Dispose() oPin1 = Nothing End If
If oPin2 IsNot Nothing Then oPin2.Dispose() oPin2 = Nothing End If
If oPinO IsNot Nothing Then oPinO.Dispose() oPinO = Nothing End If
End Try
End Sub
End Class