【问题标题】:Changing the cell background color of a 'DataGridView' in virtual mode在虚拟模式下更改“DataGridView”的单元格背景颜色
【发布时间】:2014-05-04 04:32:34
【问题描述】:

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

private void datagridview_CellValueNeeded(
    object sender, DataGridViewCellValueEventArgs e)

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

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

datagridview[e.ColumnIndex, e.RowIndex].Style.SelectionBackColor =
    component_color;

component_color 是预先确定的。但是,这种方法并没有改变颜色。我还尝试处理其他事件,例如CellEnterCellLeaveCellValueChangedRowsAddedRowLeave。但是,我从调试工作中了解到,这些事件要么永远不会触发,要么在 CellValueNeeded 事件之前触发。

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

【问题讨论】:

    标签: c# winforms


    【解决方案1】:

    您需要处理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;
    }
    

    干杯

    【讨论】:

    • 设置BackColor属性是否有效?将索引为 3 的列的 DefaultCellStyle 设置为在构造函数中分配的 new DataGridViewCellStyle{BackColor = SystemColors.Window} 不是更有效吗?而且,由于许多单元格可能包含 targetValue,将new DataGridViewCellStyle{BackColor = Color.Red} 存储在私有类字段中并重用它会更有效吗?
    • 为什么不对它进行基准测试?我的意思是,您选择了一个 4 年前的答案,然后询问这是否是完成原始发帖人所要求的最有效的方法。您是否看到有人抱怨可能的性能问题?我认为您试图提出一个不存在的性能问题。
    • 恐怕我被误解了,抱歉。
    • 改善答案永远不会太晚,IMO。 StackOverflow 的本质是协同工作,为所有读者提供最准确和最完整的答案,而不仅仅是 OP。要求澄清和/或提出替代方案,这是一件好事 (TM)
    • @LorenzoDematté 是的,我同意,但是在没有任何支持数据的情况下断言解决方案与另一个解决方案的效率是毫无意义的。如果至少该人以“我对您的解决方案进行了基准测试,并发现此其他解决方案更有效”来进行讨论。不,他根据假设做了一些断言。
    【解决方案2】:

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

    The best practices suggested by Microsofthierarchy detailed explanation 明确声明(并解释原因)应尽可能重用 DataGridViewCellStyle。

    诀窍在于,由于 CellStyle 包含继承的样式,您不能直接更改它,因此必须在访问它之前对其进行克隆。如果您有 1000 个与“目标”匹配的单元格,那么您克隆 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;
    }
    

    这种方法在非常复杂的场景中可能会受到很大限制,因为您需要事先了解所有样式和组合(例如红色背景色、白色前色以及红色背景色、黑色前色和粗体),这可能会很棘手并且麻烦。我认为无论如何微软的建议都值得一提。这不是纯粹的性能问题,更多的是知道你在做什么以及正在发生什么,以便选择最好的(什么是最好的取决于场景)策略。我认为我们需要教导年轻程序员在开发时做出明智的选择。

    请考虑我的回答不是替代性的,而是对 Luc 的回答的补充。

    一个

    【讨论】:

    • 我邀请您再次阅读“动态设置样式”部分。它明确指出,在CellFormatting 事件中,您将获得一个CellStyle 对象,并且“您可以修改单元格样式属性以指定适合单元格值和位置的样式信息”。请注意,Microsoft 自己告诉用户设置CellStyle 对象的属性。我将用同样的问题重申我对您的评论的评论:“您为什么不对其进行基准测试?”。把基准测试结果带给我们,然后我们就可以讨论一个真实的问题,而不仅仅是一个假设的问题。
    猜你喜欢
    • 2013-04-12
    • 2016-05-27
    • 2014-10-08
    • 2015-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-11
    • 2014-02-27
    相关资源
    最近更新 更多