winforms 如何根据column 1中的值自动向DataGridView的行标题添加不同颜色的图标/图像

xe55xuns  于 2023-06-30  发布在  其他
关注(0)|答案(1)|浏览(85)

如何根据column 1中的值自动添加不同颜色的图标/图像到DataGridView的行标题?
是否可以根据“COLUMN 1”中的值随机拾取所有颜色,而无需手动设置颜色,也可以取“COLUMN 1”和“COLUMN 2”之间的组合值?
谢谢

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
vwkv1x7d

vwkv1x7d1#

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

' +
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

相关问题