3

我一直在与 CellFormatting 事件作斗争,它太慢了。

我有一个像这样的 DataGridView:

在此处输入图像描述

我编写了一个函数,当您单击标题中的复选框时会触发它,它会使所有复选框都选中该列...。

private void checkboxHeader_CheckedChanged(object sender, EventArgs e)
    {
        for (int i = 0; i < dataGridView1.RowCount; i++)
        {
            dataGridView1[0, i].Value = ((CheckBox)dataGridView1.Controls.Find("checkboxHeader", true)[0]).Checked;
        }
        //dataGridView1.EndEdit();
    }  

当我有 10 行之类的东西时,这个功能可以正常工作,但是当我有 300 行时,我应该有一些东西......检查所有复选框时会有 9 秒的延迟,我发现这是由于 CellFormating 事件。

我的 CellFormating 事件代码是:

private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {

            DataGridViewCellStyle _myStyle = new DataGridViewCellStyle();
            int index = gdv_row.FindIndex(p => p.log == (string)dataGridView1.Rows[e.RowIndex].Cells[1].Value);
            if (index != -1 && dataGridView1.Columns[e.ColumnIndex] is DataGridViewTextBoxColumn && e.RowIndex != -1)
            {
                //e.CellStyle = _myStyle;
                _myStyle.Font = gdv_row[index].font;
                _myStyle.BackColor = gdv_row[index].backgroundcolor_color;
                _myStyle.ForeColor = gdv_row[index].foregroundcolor_color;
                dataGridView1.Rows[e.RowIndex].Cells[1].Style = _myStyle;
            }
        }

我已经为 DataGridView 使用了 DoubleBuffering。现在我不知道我应该如何处理这个 CellFormatting 事件......

4

3 回答 3

4

您是否已经尝试过 SuspendLayout()ResumeLayout()

这会暂时暂停控件的布局逻辑,以便在填充网格时不会重绘网格。

如果您使用 DoubleBuffering 网格仍然会重新排列本身,这仍然很慢。但是,如果您在填充网格时根本不重绘,这应该会带来显着的改善。

您的第一个函数可能如下所示:

private void checkboxHeader_CheckedChanged(object sender, EventArgs e)
    {
        dataGridView1.SuspendLayout();

        for (int i = 0; i < dataGridView1.RowCount; i++)
        {
            dataGridView1[0, i].Value = ((CheckBox)dataGridView1.Controls.Find("checkboxHeader", true)[0]).Checked;
        }

        dataGridView1.ResumeLayout();
    }  

[编辑 1]

添加了代码示例。

[编辑 2] 为了尽量减少行的必要绘制,而不是DataGridViewCellStyle为每一行创建一个新对象,尝试直接设置现有样式的属性:

    private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    {
        int index = gdv_row.FindIndex(p => p.log == (string)dataGridView1.Rows[e.RowIndex].Cells[1].Value);
        if (index != -1 && dataGridView1.Columns[e.ColumnIndex] is DataGridViewTextBoxColumn && e.RowIndex != -1)
        {
            dataGridView1.Rows[e.RowIndex].Cells[1].Style.Font = gdv_row[index].font;
            dataGridView1.Rows[e.RowIndex].Cells[1].Style.BackColor = gdv_row[index].backgroundcolor_color;
            dataGridView1.Rows[e.RowIndex].Cells[1].Style.ForeColor = gdv_row[index].foregroundcolor_color;
        }
    }

最后,寻找一些解决方案,我找到了这篇 MSDN 文章文档: Best Practices for Scaling the Windows Forms DataGridView Control

[编辑 3](回应 Ehsan 的评论如下)

这是因为“a”是一个立即显示在网格中的值,而原始行做了一些重要的工作: * 搜索所需的值,包括所有子控件 * 使用找到的结果创建一个数组 * 使从对象到 CheckBox 的转换 * 它对网格中的每一行都执行所有这些操作

很明显,您在 DataGridView 中拥有的项目越多,这就越耗时。

如果我正确理解了您的代码,它应该可以帮助您将方法更改为:

  CheckBox headerBox = ((CheckBox)dataGridView1.Controls.Find("checkboxHeader", true)[0]);
  for (int i = 0; i < dataGridView1.RowCount; i++)
  {
    dataGridView1[0, i].Value = headerBox.Checked;
  }

通过这样做,您只需执行一次搜索。

于 2012-01-03T12:12:29.637 回答
0

如果您想在检查所有行时停止绘制控件,您应该查看DrawingControl这篇文章中的类:https://stackoverflow.com/questions/487661/...

于 2012-01-03T12:31:17.593 回答
0

在我的情况下,问题是由 DataGridView 属性AutoSizeColumnsMode=AllCells引起的。可能在单元格格式化后,列和标题单元格中的所有其他单元格必须重新绘制以使其尺寸适合新的单元格尺寸。在我将属性值更改为默认值“无”后,立即绘制网格。

于 2019-08-26T11:28:09.897 回答