如何根据column1中的值自动添加不同颜色的图标/图像到DataGridView的行标题

2024-01-03

如何根据column1中的值自动添加不同颜色的图标/图像到DataGridView的行标题?

是否可以根据“COLUMN1”中的值随机选取所有颜色,而无需手动设置颜色,并且还可以取“COLUMN1”和“COLUMN2”之间的组合值?

Thanks

Private colors As Color()

Protected Overrides Sub OnLoad(e As EventArgs)
    MyBase.OnLoad(e)

    colors = {Color.Red, Color.Green, Color.Orange, 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)
        Dim colorIndex = e.RowIndex Mod colors.Length

        e.Paint(e.ClipBounds, DataGridViewPaintParts.Background Or
                DataGridViewPaintParts.Border Or
                DataGridViewPaintParts.SelectionBackground)

        Using bmp = My.Resources.SomeImage,
            ellipseBrush = New SolidBrush(colors(colorIndex))
            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

那么,您的意思是对重复的行使用相同的随机颜色?为此,您需要按单元格值对行进行分组,并为每个组使用一种颜色。这样做是在CellPainting事件是一项繁重的任务,因为它是为网格中的每个单元格引发的。因此,我建议添加一个隐藏的DataColumn to the DataTable保留每行的颜色索引。当您第一次绑定控件以及用户修改值时,会设置索引。

' +
Imports System.Reflection

Private colors As Color()
Private bmp As Bitmap

Sub New()
    InitializeComponent()

    ' To reduce the flickering...
    DataGridView1.GetType().
    GetProperty("DoubleBuffered",
                BindingFlags.Instance Or BindingFlags.NonPublic).
    SetValue(DataGridView1, True)
End Sub

Protected Overrides Sub OnLoad(e As EventArgs)
    MyBase.OnLoad(e)

    ' Collect dark colors...
    colors = GetType(Color).
        GetProperties(BindingFlags.Public Or BindingFlags.Static).
        Where(Function(pi) pi.PropertyType = GetType(Color)).
        Select(Function(pi) CType(pi.GetValue(GetType(Color), Nothing), Color)).
        Where(Function(c)
                    Return ((
                    c.R * 0.299F +
                    c.G * 0.587F +
                    c.B * 0.114F) / 256.0F) <= 0.5F
                End Function).ToArray()

    bmp = My.Resources.Money

    Dim Table1 = New DataTable("TableName")

    Table1.Columns.AddRange({
        New DataColumn("Column1", GetType(String)),
        New DataColumn("Column2", GetType(Integer)),
        New DataColumn("Column3", GetType(Integer)),
        New DataColumn("ColorIndex", 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", 75, 85)
    Table1.Rows.Add("Item4", 77, 21)
    Table1.Rows.Add("Item2", 50, 70)
    ' ...etc.

    DataGridView1.DataSource = Table1
    DataGridView1.Columns("ColorIndex").Visible = False
    UpdateColorColumn()
    Table1.AcceptChanges()
End Sub

Protected Overrides Sub OnFormClosed(e As FormClosedEventArgs)
    MyBase.OnFormClosed(e)
    bmp.Dispose()
    DirectCast(DataGridView1.DataSource, IDisposable)?.Dispose()
End Sub

Private Sub DataGridView1_CellValueChanged(sender As Object,
                e As DataGridViewCellEventArgs) _
                Handles DataGridView1.CellValueChanged
    UpdateColorColumn()
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 ellipseSize = DataGridView1.RowTemplate.Height - 3
        Dim ellipseRect = New Rectangle(
                e.CellBounds.X + (e.CellBounds.Width - ellipseSize) \ 2,
                e.CellBounds.Y + (e.CellBounds.Height - ellipseSize) \ 2,
                ellipseSize, ellipseSize)
        Dim imgSize = ellipseSize ' Or smaller...
        Dim imgRect = New Rectangle(
            ellipseRect.X + (ellipseRect.Width - imgSize) \ 2,
            ellipseRect.Y + (ellipseRect.Height - imgSize) \ 2,
            imgSize, imgSize)
        Dim drv = DirectCast(DataGridView1.Rows(e.RowIndex).DataBoundItem, DataRowView)
        Dim colorIndex = Convert.ToInt32(drv.Item("ColorIndex"))
        Dim g = e.Graphics
        Dim gs = g.Save()

        e.Paint(e.ClipBounds, DataGridViewPaintParts.Background Or
                DataGridViewPaintParts.Border Or
                DataGridViewPaintParts.SelectionBackground)

        Using ellipseBrush = New SolidBrush(colors(colorIndex))
            g.SmoothingMode = SmoothingMode.AntiAlias
            g.FillEllipse(ellipseBrush, ellipseRect)
            g.InterpolationMode = InterpolationMode.HighQualityBicubic
            g.DrawImage(bmp, imgRect, 0, 0, bmp.Width, bmp.Height,
                        GraphicsUnit.Pixel)
        End Using

        g.Restore(gs)
        e.Handled = True
    End If
End Sub

Private Sub UpdateColorColumn()
    Dim dt = DirectCast(DataGridView1.DataSource, DataTable)
    dt.EndInit()
    Dim groups = dt.AsEnumerable().
        GroupBy(Function(g) New With {
        Key .Col1 = g.Item(0),
        Key .Col2 = g.Item(1),
        Key .Col3 = g.Item(2) ' Remove this to group by the first two.
    })

    For i = 0 To groups.Count - 1
        Dim group = groups(i)
        Dim colorIndex = i Mod colors.Length

        For Each row In group
            row("ColorIndex") = colorIndex
        Next
    Next
End Sub

如果您有数据库,请填写DataTable在添加之前ColorIndex柱子。要更新数据库,您不需要对附加列执行任何特殊操作。这INSERT and UPDATE命令执行它们的 SQLCommandText查询并忽略中的任何其他内容Columns收藏。但是,您可以获得当前版本的副本DataTable并排除非数据库列。

例如:

Dim dt = Table1.DefaultView.
    ToTable(False, Table1.Columns.
    Cast(Of DataColumn).
    Where(Function(c) c.ColumnName <> "ColorIndex").
    Select(Function(c) c.ColumnName).ToArray())

作为另一种选择,使用DataGridViewRow.Tag属性来保持颜色索引。同样可以这样写。

Private colors As Color()
' ...

Protected Overrides Sub OnLoad(e As EventArgs)
    MyBase.OnLoad(e)

    ' ...

    DataGridView1.DataSource = Table1
    UpdateColorIndices()
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 ellipseSize = DataGridView1.RowTemplate.Height - 3
        Dim ellipseRect = New Rectangle(
                e.CellBounds.X + (e.CellBounds.Width - ellipseSize) \ 2,
                e.CellBounds.Y + (e.CellBounds.Height - ellipseSize) \ 2,
                ellipseSize, ellipseSize)
        Dim imgSize = ellipseSize
        Dim imgRect = New Rectangle(
            ellipseRect.X + (ellipseRect.Width - imgSize) \ 2,
            ellipseRect.Y + (ellipseRect.Height - imgSize) \ 2,
            imgSize, imgSize)
        Dim colorIndex = Convert.ToInt32(DataGridView1.Rows(e.RowIndex).Tag)
        Dim g = e.Graphics
        Dim gs = g.Save()

        e.Paint(e.ClipBounds, DataGridViewPaintParts.Background Or
                DataGridViewPaintParts.Border Or
                DataGridViewPaintParts.SelectionBackground)

        Using ellipseBrush = New SolidBrush(colors(colorIndex))
            g.SmoothingMode = SmoothingMode.AntiAlias
            g.FillEllipse(ellipseBrush, ellipseRect)
            g.InterpolationMode = InterpolationMode.HighQualityBicubic
            g.DrawImage(bmp, imgRect, 0, 0, bmp.Width, bmp.Height,
                        GraphicsUnit.Pixel)
        End Using

        g.Restore(gs)
        e.Handled = True
    End If
End Sub

Private Sub UpdateColorIndices()
    DataGridView1.EndEdit()
    Dim groups = DataGridView1.Rows.Cast(Of DataGridViewRow).
        Where(Function(r) r.Index <> DataGridView1.NewRowIndex).
        GroupBy(Function(r) New With {
        Key .Col0 = r.Cells(0).Value,
        Key .Col1 = r.Cells(1).Value,
        Key .Col2 = r.Cells(2).Value
    })

    For i = 0 To groups.Count - 1
        Dim index = i Mod colors.Length
        For Each row In groups(i)
            row.Tag = index
        Next
    Next
    DataGridView1.Invalidate()
End Sub

另外,您可以创建一个Dictionay(Of Integer, Color)其中每个KeyValuePair保存行索引和椭圆颜色。

Private colors As Color()
Private ReadOnly dictColors As New Dictionary(Of Integer, Color)
' ...

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 ellipseSize = DataGridView1.RowTemplate.Height - 3
        Dim ellipseRect = New Rectangle(
                e.CellBounds.X + (e.CellBounds.Width - ellipseSize) \ 2,
                e.CellBounds.Y + (e.CellBounds.Height - ellipseSize) \ 2,
                ellipseSize, ellipseSize)
        Dim imgSize = ellipseSize
        Dim imgRect = New Rectangle(
            ellipseRect.X + (ellipseRect.Width - imgSize) \ 2,
            ellipseRect.Y + (ellipseRect.Height - imgSize) \ 2,
            imgSize, imgSize)
        Dim g = e.Graphics
        Dim gs = g.Save()

        e.Paint(e.ClipBounds, DataGridViewPaintParts.Background Or
                DataGridViewPaintParts.Border Or
                DataGridViewPaintParts.SelectionBackground)

        Using ellipseBrush = New SolidBrush(dictColors(e.RowIndex))
            g.SmoothingMode = SmoothingMode.AntiAlias
            g.FillEllipse(ellipseBrush, ellipseRect)
            g.InterpolationMode = InterpolationMode.HighQualityBicubic
            g.DrawImage(bmp, imgRect, 0, 0, bmp.Width, bmp.Height,
                        GraphicsUnit.Pixel)
        End Using

        g.Restore(gs)
        e.Handled = True
    End If
End Sub

Private Sub UpdateColorIndices()
    DataGridView1.EndEdit()
    dictColors.Clear()
    Dim groups = DataGridView1.Rows.Cast(Of DataGridViewRow).
        Where(Function(r) r.Index <> DataGridView1.NewRowIndex).
        GroupBy(Function(r) New With {
        Key .Col0 = r.Cells(0).Value,
        Key .Col1 = r.Cells(1).Value,
        Key .Col2 = r.Cells(2).Value
    })

    For i = 0 To groups.Count - 1
        Dim index = i Mod colors.Length
        For Each row In groups(i)
            dictColors(row.Index) = colors(index)
        Next
    Next
    DataGridView1.Invalidate()
End Sub
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何根据column1中的值自动添加不同颜色的图标/图像到DataGridView的行标题 的相关文章

  • 将 Windows 窗体应用程序转换为 Asp.net

    我问的是 您之前使用的将 C Windows 窗体应用程序转换为 ASP NET 的最佳工具是什么 我已经关于这个主题 发现了很多工具 但我希望有人根据他的使用情况推荐最好的工具 我真的不建议使用工具来进行转换 Web 应用程序和 WinF
  • C#:如何防止主窗体过早显示

    在我的 main 方法中 我像往常一样启动主窗体 Application EnableVisualStyles Application SetCompatibleTextRenderingDefault false Application
  • 在 VB 2010 中禁用“默认实例”

    我已经开始在 VB 2010 中做一些基本的 win 表单工作 我真的很烦恼默认实例 https stackoverflow com q 4698538 794234特征 有没有办法可以完全禁用它并像普通类一样使用这些类 向表单的构造函数添
  • DataGrid使用SQLDataAdapter更新问题

    我有一个漂亮的小型 DataGridView 它由一个按钮 一个 SQLDataAdapter 和相应的 saveButton 加载 填充 private void loadButton Click object sender EventA
  • 匹配所有有效格式 IPv6 地址的正则表达式

    乍一看 我承认这个问题看起来像是这个问题以及与之相关的任何其他问题的重复 匹配有效 IPv6 地址的正则表达式 https stackoverflow com questions 53497 regular expression that
  • 使用 Graphics.FromHwnd 在屏幕上绘图和清除

    我正在尝试创建一个程序 它获取光标下窗口的句柄 显示有关它的一些数据 并在整个窗口的顶部绘制一个填充矩形 具有非常低的阿尔法 我正在使用 C 和 winforms 我已经成功地做到了这一点 但问题是我的绘制方法位于BackgroundWor
  • WPF DataGrid 验证/绑定模式错误

    我创建了一个非常简单的新项目 仅测试 Microsoft WPF DataGrid 行为 不涉及其他 我只使用标准的 DataGrid
  • 当文本框中有字符串时如何启用按钮?

    我在 form2 中有一个文本框和一个按钮 当单击 form1 中的某个项目时 将出现 form2 我想在文本框为空时保持 form2 中的按钮处于禁用状态 但是当用户开始输入时 我想启用该按钮 我尝试在构造函数中像这样在initialis
  • 尚未处理时调用 Form 的 Invoke 时出现 ObjectDisposeException

    我们得到一个ObjectDisposedException从一个电话到Invoke在尚未处理的表格上 这是一些演示该问题的示例代码 public partial class Form2 Form void Form2 Load object
  • 实例化 Microsoft.Office.Interop.Excel.Application 对象时出现错误:800700c1

    实例化 Microsoft Office Interop Excel Application 以从 winforms 应用程序生成 Excel 时 出现以下错误 这之前是有效的 但突然间它停止工作了 尽管代码和 Excel 版本没有变化 我
  • 使用按钮在表单之间传递变量[重复]

    这个问题在这里已经有答案了 我想知道如何将一个整数从 form1 传递到 form2 我尝试通过打开 form2 的按钮来执行此操作 但事件按钮单击无法识别整数 我该怎么办 在form1中 我有整数x 我希望当我单击button1时 for
  • vb6 中双精度计算的值不正确

    当在 vb6 中添加 2 个值时 我得到一些奇怪的行为 当在立即窗口中针对不同情况打印变量 sum 双精度型 时 如下所示 我得到的结果为 sum 0 sum 0 sum 0 sum 74 46 0 41 sum 74 87 sum 97
  • 在 C# 中在 Windows 标题栏区域中创建选项卡

    有人可以告诉我如何在 C Winforms 应用程序的标题栏区域中创建选项卡吗 我正在寻找类似于 Google Chrome 的外观 Chrome 中的每个选项卡都停靠在主应用程序窗口的标题栏中 尝试将表单的 FormBorderStyle
  • VB无法访问不同项目中的类,相同的解决方案

    我正在使用 VB for Visual Studio 工作 并且项目中有一个类需要将变量声明为另一个项目中的类 对于可视化 解决方案 A 包含 Project1 和 Project2 在 Project1 的类中 我需要声明一个变量作为 P
  • 简单的if检查多个值vb

    在Sql中我们可以像这样过滤 SELECT FROM 表名 WHERE 列名 IN firstValue secondValue 如何在VB Net中检查 有简单的方法吗 或者 只是 If variable firstValue Or va
  • ODP.Net - OracleDataReader.读取速度非常慢

    我在 ODP Net 中的 OracleDataReader 方面遇到很多麻烦 基本上 我有一个参数化查询 需要 1 5 秒的时间来运行 返回大约 450 条记录 然后需要 60 90 秒的时间来循环 甚至没有代码在循环中运行 实际上是迭代
  • C# Winform - 当用手指在触摸屏上移动到控件末尾时如何防止移动整个窗口

    我正在开发用于触摸屏的全屏 winform 应用程序 当我在表单上有任何控件时 例如listbox webBrowserControl 它具有可见的滚动条 有要滚动的内容 当我用手指移动到控件的末尾时 完整的表单向上 向下移动取决于移动方向
  • 使用 DirectCast、CType、TryCast 转换数据类型

    自从我在 2005 年从 VB6 迁移到 VB NET 以来 我一直在使用 CType 将一种数据类型转换为另一种数据类型 我这样做是因为它打字速度更快 以前存在于 VB6 中 而且我不知道为什么我必须使用 DirectCast 如果它们之
  • 如何在多线程应用程序中安全地填充数据并 Refresh() DataGridView?

    我的应用程序有一个 DataGridView 对象和一个 MousePos 类型的列表 MousePos 是一个自定义类 它保存鼠标 X Y 坐标 类型为 Point 和该位置的运行计数 我有一个线程 System Timers Timer
  • 将键码转换为相关的显示字符

    在 C Windows Forms 项目中 我有一个不提供 KeyPressed 事件的控件 它是一个 COM 控件 ESRI 映射 它仅提供 KeyUp 和 KeyDown 事件 包含关键事件参数 http msdn microsoft

随机推荐