为什么连续调用 RowPrePaint?

Why is RowPrePaint being called continuously?

我有一个 DataGridView 并像这样实现了 RowPrePaint 事件:

private void dgData_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e)
{
    int multiplier = (int)dgData.Rows[e.RowIndex].Cells["multiplier"].Value;
    bool marked = (bool)(dgData.Rows[e.RowIndex].Tag ?? false);

    if (multiplier > 1)
    {
        dgData.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.FromArgb(0xff, 0xf2, 0xf2, 0xff);
    }
    if (marked)
    {
        dgData.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.FromArgb(0xff, 0xff, 0xff, 0xf2);
    }
}

当我拥有所有这些代码时,我可以看到我的网格正在不断地重新绘制(添加日志语句时确认)。当我注释掉代码时,只在需要时才重新绘制。

为什么会这样?

通过更改 RowPrePaint 事件中的单元格样式,您实际上是在要求该行重新绘制自身,从而再次触发所述事件。如果颜色每次都改变,这甚至可以无限期地重复,如下面的代码所示:

private static Random random = new Random();
private void dgData_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e)
{
    dgData.Rows[e.RowIndex].DefaultCellStyle.BackColor = 
        Color.FromArgb(random.Next(0, 256), 0xf2, 0xf2, 0xff);
}

针对您的具体情况,我可以想到两种更改单元格样式的方法。

  1. 如果您需要更改行的实际 DefaultCellStyle,并且由于颜色是(部分)根据单元格值确定的,您可以处理 CellValueChanged事件。假设行的 Tag 属性 没有改变,你就可以开始了。否则,您需要在更改行标记后执行相同的代码。

  2. 如果您只想更改显示的颜色,您可以使用 CellFormatting 事件,该事件通过其 EventArgs 公开 DataGridViewCellStyle 属性。不要在那个事件中改变 DefaultCellStyle ,否则,你会遇到同样的问题(重新触发同样的事件)。相反,您可以使用 e.CellStyle 来达到相同的目的:

    private void dgData_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    {
        e.CellStyle.BackColor = Color.FromArgb(...);
    }