滚动 DataGridView 会破坏 CellPainting 和 RowPostPaint 事件绘制的任何内容

Scrolling DataGridView botches anything painted by CellPainting and RowPostPaint events

首先让我说我找到了以下内容,但其中 none 个有适合我的解决方案。

DataGridView overrides my custom row painting

DataGridView CellPainting Not Fully Working on Scroll


在 CellPainting 和 RowPostPaint 中,我都使用 e.Graphics.DrawLine,当网格加载时,一切都按照我的预期绘制。我有两个问题:

  1. 当我水平滚动时,屏幕上最初不可见的任何内容都没有我的自定义绘画,并且
  2. 当我向后滚动时,一些已经绘制的线条已经移动以创建一条穿过单元格中间的线,而不是像滚动之前那样位于边框上。

这是我的两个绘画事件:

private void dataGridView1_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
{
    int width = 0;
    foreach (DataGridViewColumn col in dataGridView1.Columns)
    {
        width += col.Width;
        if (col.Index % 3 == 0)
            e.Graphics.DrawLine(Pens.Black, width + 1, e.RowBounds.Top, width + 1, e.RowBounds.Bottom - 1);
    }
}
private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
    int width = 0;
    if (e.RowIndex == -1)
    {
        foreach (DataGridViewColumn col in dataGridView1.Columns)
        {
            width += col.Width;
            if (col.Index % 3 == 0)
                e.Graphics.DrawLine(Pens.Black, width + 1, e.CellBounds.Top +1, width + 1, e.CellBounds.Bottom - 2);
            else
                e.Graphics.DrawLine(Pens.White, width + 1, e.CellBounds.Top +1, width + 1, e.CellBounds.Bottom - 2);
        }
    }
}

更新代码 从那以后,我将我的绘画事件合并到 CellPainting 事件中,并按照 TaW 的建议进行了一些更改。仍然无法正常工作,但我觉得此时我只是遗漏了一些小东西。

private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
    if (e.RowIndex == -1)
    {
        if (e.ColumnIndex % 3 == 0)
            e.Graphics.DrawLine(Pens.Black, e.CellBounds.Right, e.CellBounds.Top + 1, e.CellBounds.Right, e.CellBounds.Bottom - 2);
        else
            e.Graphics.DrawLine(Pens.White, e.CellBounds.Right, e.CellBounds.Top + 1, e.CellBounds.Right, e.CellBounds.Bottom - 2);
    }
    else
        if (e.ColumnIndex % 3 == 0)
            e.Graphics.DrawLine(Pens.Black, e.CellBounds.Right, e.CellBounds.Top + 1, e.CellBounds.Right, e.CellBounds.Bottom - 2);
}

您缺少几个正确的步骤 CellPainting:

你需要

  • 告诉事件你已经完成了,否则一切都会被覆盖 (1)
  • 因此您还需要确保..
    • 背景 (2) and..
    • 内容(3)绘制。

这是一个例子:

    private void dataGridView1_CellPainting(object sender, 
                                            DataGridViewCellPaintingEventArgs e)
    {
        Rectangle cr = e.CellBounds;
        e.PaintBackground(cr, true);  //  (2)
        e.PaintContent(cr);           //  (3)

        if (e.ColumnIndex % 2 == 0)
        {
                e.Graphics.DrawLine(Pens.LawnGreen, cr.Right-2, cr.Top + 1, 
                                                    cr.Right-12, cr.Bottom - 2);
        }

        e.Handled = true;  // (1)
    }

您可以更改事物的顺序,只要确保先绘制背景即可!

请注意,与注释相反,无需使用 InvalidateScroll 事件进行编码。