向DataGridView添加行的速度太慢了。

4

我有一个 DataGridView,我通过以下方式填充它:

private void FillDataGridView(string stringTable)
{
    var lines = stringTable.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);

    var columns = lines.First().Split('\t');
    foreach (var columnName in columns)
        this.dataGridView.Columns.Add(columnName, columnName);

    foreach (var line in lines.Skip(1))
    {
        var cells = line.Split('\t');
        // This operation is too slow when applied to a huge amount of rows:
        this.dataGridView.Rows.Add(cells);                
    }            
}

我的问题是Rows.Add(cells)太慢了(我有大量数据)。

这是stringTable内容的示例:

TIME    Temperature
30.03.1992 10:00:00 7.500
30.03.1992 11:00:00 9.300
30.03.1992 12:00:00 10.000
30.03.1992 13:00:00 10.400
30.03.1992 14:00:00 11.400
30.03.1992 15:00:00 11.800
...

我想使用 BindingList 并将其设置为 DataSource,这样会使它运行更快。问题在于,我事先不知道列数(在此示例中只有“TIME,Temperature”,但它可能是“TIME,Temperature,Rainfall,...,Other”)。


最大列集是否提前已知?如果是,可以使用静态数据网格来包含所有这些列,并根据您绑定的特定数据隐藏列。然后,您可以创建一个数据源,其中包含所有列,但只填充了相关数据的列。 - user469104
2个回答

5
不要在循环中逐行向网格添加行。首先在循环中创建所有行,然后通过一次调用 "AddRange" 将它们全部添加到网格中。
或者,填充 DataTable 或其他适合的列表,然后将其绑定到网格。
如果数据量仍然太大而速度太慢,那么您可能需要考虑对网格进行虚拟化处理。

关于在循环中创建行,我尝试过这种方法,但是我发现似乎无法独立地创建行。请参考以下答案:https://dev59.com/72kw5IYBdhLWcg3wMHun#10063825 <= 所有这些创建新的数据行的方式都很复杂,而且似乎依赖于DataGridView本身。 - Xavier Peña
等等,看起来第二个建议(“或者,填充一个DataTable或其他适当的列表,然后将其绑定到网格中”)已经足够好了!谢谢!如果其他人正在寻找同样的东西:1)var dataTable = new DataTable();,2)向dataTable添加列,3)dataTable.Rows.Add(cells);,以及4)this.dataGridView.DataSource = dataTable; - Xavier Peña
1
对我来说,AddRange 快大约 10 倍。填充列表并在初始化之前对每行调用 CreateCells 的代码只会丑陋 2 倍。 - Andreas Reiff

0

如果您不想更改您的代码,请尝试以下方法:

  • FillDataGridView期间暂停DataGridView绘制
  • 在过程结束时恢复DataGridView绘制

要暂停控件绘制,您可以使用以下代码:

SendMessage(ctrlControl.Handle, WM_SETREDRAW, 0, 0)

要恢复控制绘图,您可以使用以下代码:

SendMessage(ctrlControl.Handle, WM_SETREDRAW, 1, 0)
ctrlControl.Refresh()

记得使用 Try/Catch/Finally 块来防止出现问题,以防 DataGridView 绘制被暂停。

Try
    Application.DoEvents()

    Me.Cursor = Cursors.WaitCursor

    SuspendControlDrawing(yourDataGridView)

    FillDataGridView(stringTable)

Catch ex As Exception
    MsgBox(ex.Message)

Finally

    Try
        ResumeControlDrawing(yourDataGridView)
    Catch ex As Exception
    End Try

    Me.Cursor = Cursors.Default

End Try

使用SuspendLayout和ResumeLayout与简单地使用有什么不同/优势吗? - TaW
如果我没记错的话,SuspendLayout和ResumeLayout会出现闪烁问题。 - tezzo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接