C#中的CellFormatting事件非常慢

时间:2012-01-03 11:59:38

标签: c# performance cell-formatting

我一直在与CellFormatting事件挣扎,它太慢了。

我有一个像这样的DataGridView:

enter image description here

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

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;
            }
        }

我使用了DoubleBuffering for DataGridView。现在我不知道我应该怎么做这个CellFormatting事件...

3 个答案:

答案 0 :(得分:3)

您是否已尝试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;
  }

通过执行此操作,您只需执行一次搜索。

答案 1 :(得分:0)

如果您想在检查所有行时停止绘制控件,则应该查看此帖子中的DrawingControl课程:https://stackoverflow.com/questions/487661/...

答案 2 :(得分:0)

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