C# 更改';DataGridView';在虚拟模式下

C# 更改';DataGridView';在虚拟模式下,c#,winforms,C#,Winforms,我正在学习如何在虚拟模式下使用DataGridView控件。我使用一个列表数组来存储一个文本文件的内容,它可以是小的,也可以是相当大的。DataGridView中的一个特定列需要根据单元格中的文本内容更改单元格的背景色。因此,我有一个事件处理程序: private void datagridview_CellValueNeeded( object sender, DataGridViewCellValueEventArgs e) 填充DataGridView的每一行。我的问题是,我不知

我正在学习如何在虚拟模式下使用
DataGridView
控件。我使用一个列表数组来存储一个文本文件的内容,它可以是小的,也可以是相当大的。
DataGridView
中的一个特定列需要根据单元格中的文本内容更改单元格的背景色。因此,我有一个事件处理程序:

private void datagridview_CellValueNeeded(
    object sender, DataGridViewCellValueEventArgs e)
填充
DataGridView
的每一行。我的问题是,我不知道在哪里插入代码来设置背景色,因为每行中都创建了单元格(现在处于虚拟模式)

我尝试使用
CellValueRequired
的事件处理程序,首先检查特定的列ID,然后设置单元格背景颜色,如下所示:

datagridview[e.ColumnIndex, e.RowIndex].Style.SelectionBackColor =
    component_color;
其中,
组件颜色
是预先确定的。然而,这种方法并没有改变颜色。我还尝试处理其他事件,如
CellEnter
CellLeave
CellValueChanged
RowsAdded
RowLeave
。但是,我从调试工作中了解到,这些事件要么从未触发,要么在
CellValueRequired
事件之前触发


那么,是否可以通过处理
CellValueNeeded
事件来设置在特定列中创建的单元格的背景色?或者我应该通过处理不同的事件来实现这一点吗?

您需要处理
DataGridView.CellFormatting
事件。例如:

private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    if (e.ColumnIndex == 3 && e.Value == targetValue)
        e.CellStyle.BackColor = Color.Red;
    else
        e.CellStyle.BackColor = SystemColors.Window;
}
干杯

尽管答案在形式上是正确的,并且适用于所有场景,但值得注意的是,在CellStyle属性上指定单个属性将克隆()完整的原始继承样式

并且尽可能地重用DataGridViewCellStyle(并解释其原因)

诀窍在于,由于CellStyle包含继承的样式,您不能直接更改它,因此必须在访问它之前对其进行克隆。如果有1000个单元格与“target”匹配,则克隆1000倍相同的继承样式,只需应用1000倍相同的样式(红色背景)。因此,最佳实践是:将列默认设置为该列的预期默认样式,然后创建一次“突出显示”单元样式,并在可能的情况下重用它

在几乎所有情况下,不会注意到差异,也不会注意到任何类型的惩罚(内存、cpu、闪烁等)。尽管如此,我相信重要的是要理解在幕后有很多事情正在发生。此外,CellFormatting经常被调用,因此保持底层操作的快速非常重要,以避免副作用

上述答案也可以这样改写:

private static DataGridViewCellStyle m_targetValueCellStyle = new DataGridViewCellStyle{ BackColor = Color.Red};

// Somewhere (i.e. in the constructor after InitializeComponents() ) set:
// dataGridView1.Columns[3].DefaultCellStyle = new DataGridViewCellStyle{ BackColor = SystemColors.Window};

private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    if (e.ColumnIndex == 3 && e.Value == targetValue)
        e.CellStyle = m_targetValueCellStyle;
}
这种方法在非常复杂的场景中可能非常有限,因为您需要事先了解所有样式和组合(例如,红色背景色、白色前景色,但也包括红色背景色、黑色前景色和粗体),这可能会很棘手和麻烦。我认为微软的建议无论如何都值得一提。在这里,这不是一个纯粹的性能问题,更重要的是了解您正在做什么和正在发生什么,以便选择最佳(最佳方案取决于场景)策略。我相信我们需要教会年轻的程序员在开发时做出明智的选择

请考虑我的答案不是替代的,而是补充卢克的一个。


A

设置BackColor属性是否有效?将索引为3的列的DefaultCellStyle设置为构造函数中指定的新DataGridViewCellStyle{BackColor=SystemColors.Window}不是更有效吗?而且,由于许多单元格可能包含targetValue,将
新的DataGridViewCellStyle{BackColor=Color.Red}
存储在私有类字段中并重用它会更有效吗?为什么不对其进行基准测试?我的意思是,你选择了一个4年前的答案,然后问这是否是实现原始海报要求的最有效的方式。您是否看到有人抱怨可能出现的性能问题?我想你是在试图提出一个不存在的性能问题。我担心我被误解了,对不起。我认为,改进答案永远不会太迟。StackOverflow的本质是合作,为所有读者提供最准确、最完整的答案,LorenzoDematté是的,我同意,不仅仅是OP.要求澄清和/或提出替代方案是件好事(TM)@LorenzoDematté是的,但是在没有任何支持数据的情况下,断言一个解决方案相对于另一个解决方案的效率是毫无意义的。如果至少该人与“我在您的解决方案上运行了一个基准测试,发现另一个解决方案更有效。”不,他根据一个假设做出了一些断言。我请您再次阅读“动态设置样式”部分。它清楚地指出,在
CellFormatting
事件中,您得到了一个
CellStyle
对象,并且”您可以修改单元格样式属性,以指定适合单元格值和位置的样式信息。请注意,Microsoft自己会告诉用户设置
CellStyle
对象的属性。我将对您的评论重申我的评论,并提出同样的问题:“为什么不对其进行基准测试?”?“。给我们带来基准测试结果,然后我们可以讨论一个真实的问题,而不仅仅是一个假设的问题。