如何为DataGridView行标题自动添加不同颜色图标?支持随机配色及多列关联
基于DataGridView列值自定义行标题图标与颜色方案
一、基于Column1值匹配固定颜色图标
原代码是按行索引循环颜色,要实现按Column1值对应固定颜色,我们可以用字典存储Column1值与颜色的映射关系,在CellPainting事件中根据当前行的Column1值获取对应颜色:
' 存储Column1值到颜色的映射 Private columnColorMap As New Dictionary(Of String, Color) Protected Overrides Sub OnLoad(e As EventArgs) MyBase.OnLoad(e) ' 初始化Column1对应的固定颜色 columnColorMap.Add("Item1", Color.Red) columnColorMap.Add("Item2", Color.Green) columnColorMap.Add("Item3", Color.Orange) columnColorMap.Add("Item4", Color.Black) Dim Table1 = New DataTable("TableName") Table1.Columns.AddRange({ New DataColumn("Column1", GetType(String)), New DataColumn("Column2", GetType(Integer)), New DataColumn("Column3", GetType(Integer)) }) Table1.Rows.Add("Item1", 44, 99) Table1.Rows.Add("Item2", 50, 70) Table1.Rows.Add("Item3", 75, 85) Table1.Rows.Add("Item2", 60, 70) Table1.Rows.Add("Item3", 85, 85) Table1.Rows.Add("Item4", 77, 21) Table1.Rows.Add("Item2", 60, 70) DataGridView1.RowTemplate.Height = 48 DataGridView1.RowHeadersWidth = 48 DataGridView1.DataSource = Table1 End Sub Private Sub DataGridView1_CellPainting(sender As Object, e As DataGridViewCellPaintingEventArgs) Handles DataGridView1.CellPainting If e.RowIndex >= 0 AndAlso e.ColumnIndex = -1 AndAlso e.RowIndex <> DataGridView1.NewRowIndex Then Dim g = e.Graphics Dim sz = Math.Min(e.CellBounds.Width, e.CellBounds.Height) - 6 Dim ellipseRect = New Rectangle( e.CellBounds.X + (e.CellBounds.Width - sz) \ 2, e.CellBounds.Y + (e.CellBounds.Height - sz) \ 2, sz, sz) Dim imgRect = Rectangle.Inflate(ellipseRect, -3, -3) ' 获取当前行的Column1值 Dim column1Value = DataGridView1.Rows(e.RowIndex).Cells("Column1").Value.ToString() ' 从字典中获取对应颜色,无匹配项时默认用灰色 Dim currentColor = If(columnColorMap.ContainsKey(column1Value), columnColorMap(column1Value), Color.Gray) ' 绘制单元格背景、边框等基础元素 e.Paint(e.ClipBounds, DataGridViewPaintParts.Background Or DataGridViewPaintParts.Border Or DataGridViewPaintParts.SelectionBackground) ' 绘制带颜色的椭圆背景和图标 Using bmp = My.Resources.SomeImage, ellipseBrush = New SolidBrush(currentColor) g.SmoothingMode = SmoothingMode.AntiAlias g.FillEllipse(ellipseBrush, ellipseRect) g.SmoothingMode = SmoothingMode.None g.DrawImage(bmp, imgRect, 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel) End Using e.Handled = True End If End Sub
说明:用Dictionary存储对应关系,保证同一Column1值的行标题颜色完全统一,比原代码按行索引循环的方式更贴合需求。
二、基于Column1值自动生成随机颜色(同一值颜色一致)
如果不想手动设置颜色,可在第一次遇到某个Column1值时生成随机颜色并存入字典,后续复用该颜色:
' 存储Column1值到颜色的映射 Private columnColorMap As New Dictionary(Of String, Color) ' 随机颜色生成器 Private rand As New Random() Protected Overrides Sub OnLoad(e As EventArgs) MyBase.OnLoad(e) ' 无需手动添加颜色,改为动态生成 ' ... 表格初始化代码与上述一致 ... End Sub Private Sub DataGridView1_CellPainting(sender As Object, e As DataGridViewCellPaintingEventArgs) Handles DataGridView1.CellPainting If e.RowIndex >= 0 AndAlso e.ColumnIndex = -1 AndAlso e.RowIndex <> DataGridView1.NewRowIndex Then ' ... 矩形、绘图对象初始化代码与上述一致 ... Dim column1Value = DataGridView1.Rows(e.RowIndex).Cells("Column1").Value.ToString() Dim currentColor As Color ' 字典无该值时生成随机颜色并存入 If Not columnColorMap.ContainsKey(column1Value) Then ' 生成亮度适中的随机颜色,避免太暗/太亮导致图标看不清 currentColor = Color.FromArgb(rand.Next(50, 200), rand.Next(50, 200), rand.Next(50, 200)) columnColorMap.Add(column1Value, currentColor) Else currentColor = columnColorMap(column1Value) End If ' ... 后续绘制代码与上述一致 ... End If End Sub
说明:通过Random生成RGB值在50-200之间的颜色,用字典缓存确保同一Column1值的行标题颜色始终相同。
三、结合Column1和Column2的值进行判断
若需同时依据两个列的值决定颜色,可直接在代码中添加判断逻辑:
Private Sub DataGridView1_CellPainting(sender As Object, e As DataGridViewCellPaintingEventArgs) Handles DataGridView1.CellPainting If e.RowIndex >= 0 AndAlso e.ColumnIndex = -1 AndAlso e.RowIndex <> DataGridView1.NewRowIndex Then ' ... 前面的初始化代码 ... Dim column1Value = DataGridView1.Rows(e.RowIndex).Cells("Column1").Value.ToString() Dim column2Value = CInt(DataGridView1.Rows(e.RowIndex).Cells("Column2").Value) Dim currentColor As Color ' 结合Column1和Column2判断颜色 Select Case column1Value Case "Item1" currentColor = Color.Red Case "Item2" ' Item2的情况下,Column2>55用深蓝色,否则用绿色 currentColor = If(column2Value > 55, Color.DarkBlue, Color.Green) Case "Item3" ' Item3的情况下,Column2>=80用橙色,否则用黄色 currentColor = If(column2Value >= 80, Color.Orange, Color.Yellow) Case Else currentColor = Color.Gray End Select ' ... 后续绘制代码 ... End If End Sub
说明:通过Select Case结合双列值做精细化判断,你可根据实际需求调整判断条件和对应颜色。
内容的提问来源于stack exchange,提问作者roy
相关产品推荐
相关产品推荐

