DataGridViewCell - 在不失去焦点的情况下更改背景颜色

DataGridViewCell - Change BackColor without losing focus

我有一个 DataGridView,其中一列显示颜色。该列包含 DataGridViewTextBox 类型,我将其留空并更改 Style.BackColor.

当用户单击单元格时,我打开一个 ColorDialog 并使用生成的颜色来设置单元格的 BackColor。然而,正如在两个类似问题 ( and DataGridViewCell Background Color Change Without Losing Focus) 中指出的那样,在单元格失去焦点之前,显示不会更改 BackColor,无论是用户单击别处还是代码执行 DataGridView.CurrentCell.Selected=False

我想知道:当单元格失去焦点时 .NET 中发生了什么,允许它重新绘制,我可以直接调用它吗?

取消选择单元格确实有效,但我想避免这种情况,因为我想保持该行处于选中状态,也因为我不想触发我不打算触发的任何其他事件。

我下面的代码(请注意,在网格刷新期间,CondColor 列的选择突出显示设置为透明):

Private Sub RefreshCondGrid()
    DataGridConditions.AutoGenerateColumns = False
    Dim sql = "SELECT *, iif(BLCond='N','New',iif(BLCond='U','Used','')) BLCondName FROM Inventory.Condition_List;"
    DataGridConditions.DataSource = GetTable(sql)
    For Each row As DataGridViewRow In DataGridConditions.Rows
        row.Cells("CondColor").Style.SelectionBackColor = Color.Transparent
        If row.DataBoundItem IsNot Nothing AndAlso Not IsDBNull(row.DataBoundItem("ColorInt")) Then
            row.Cells("CondColor").Style.BackColor = Color.FromArgb(row.DataBoundItem("ColorInt"))
        End If
    Next
End Sub
Private Sub DataGridConditions_CellContentClick(sender As DataGridView, e As DataGridViewCellEventArgs) Handles DataGridConditions.CellClick
    If sender.Columns(e.ColumnIndex).Name = "CondColor" Then
        Dim item = sender.Rows(e.RowIndex).DataBoundItem
        If Not IsDBNull(item("ColorInt")) Then
            ColorDialog1.Color = Color.FromArgb(item("ColorInt"))
        End If
        ColorDialog1.ShowDialog()
        item("ColorInt") = ColorDialog1.Color.ToArgb
        sender.Rows(e.RowIndex).Cells(e.ColumnIndex).Style.BackColor = ColorDialog1.Color
    End If
End Sub

注意:选择突出显示不会以任何方式遮盖颜色单元格

试试这个……为单元格背景设置颜色后,调用网格 EndEdit 然后立即调用网格 BeginEdit. 这应该会导致网格重绘并立即显示所选颜色并将其保留为选定的单元格。

If sender.Columns(e.ColumnIndex).Name = "CondColor" Then
  Dim item = sender.Rows(e.RowIndex).DataBoundItem
  If Not IsDBNull(item("ColorInt")) Then
    ColorDialog1.Color = Color.FromArgb(item("ColorInt"))
  End If
  ColorDialog1.ShowDialog()
  item("ColorInt") = ColorDialog1.Color.ToArgb
  sender.Rows(e.RowIndex).Cells(e.ColumnIndex).Style.BackColor = ColorDialog1.Color
  DataGridConditions.EndEdit()
  DataGridConditions.BeginEdit(False)
End If

此外,顺便说一句,发布的代码只有在编译器 Option strict 设置为 OFF. 时才有效。打开此选项是一种很好的做法。不幸的是,如果打开当前代码,它会抛出一些错误。只是一个想法。

为了扩展 dr.null 的解决方案,DataGridView 中有多层绘图。

BackColor 位于 SelectionBackColor 下方(仅在选择行时出现),对于大多数记录,将 BackColor 设置为所需颜色并将 SelectionBackColor 设置为透明将显示所需的 BackColor。

但是,当第一次绘制 DataGridView 时,在设置颜色之前选择了一条记录。在 .NET 中,如果记录已被选中,则根本不会绘制 BackColor。直到取消选择记录后才会绘制它。因此,将当前选定行的背景色设置为 Color.Orange,并将 SelectedBackColor 设置为 Color.Transparent,将显示先前为该行设置的任何背景色。

因此,要解决此问题,至少对于当前选定的行,但对于所有行来说,好的做法是将 SelectedBackColor 设置为所需的颜色,而不是透明。

重申一下 - Color.Transparent 按预期工作 - 问题是 .NET 未能首先绘制 BackColor。