使用大数据填充DatagridView时性能下降

Vij*_*ade 17 c# performance datagridview

我正在使用BindingSource控件来填充datagridview控件.它上面有大约1000多条记录.我正在使用线程来这样做.在这种情况下,datagridview执行速度非常慢.

我尝试将DoubleBuffered属性设置为true,将RowHeadersWidthSizeMode设置为禁用,将AutoSizeColumnsMode设置为none.但仍然是相同的行为.

请帮助我.如何提高网格的性能.

在此先感谢,
Vijay

oka*_*pov 26

如果你有大量的行,比如10 000或更多,

避免性能泄漏 - 在数据绑定之前执行以下操作:

dataGridView1.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.EnableResizing; 
// or even better, use .DisableResizing. Most time consuming enum is DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders

// set it to false if not needed
dataGridView1.RowHeadersVisible = false;
Run Code Online (Sandbox Code Playgroud)

数据绑定后,您可以启用它.

  • 我试着把你的代码放在我的 file.Designer.vb 中,我试着正确地运行它。正如您所说,将 RowHeadersVisible 设置为 False 然后……在 Binding 之后,再次将其 RowHeadersVisible 设置为 True。这是一个很好的解决方案,它有效!但不幸的是,如果我对 GUI (Front) 进行了一些更改,我放在 file.Designer.vb 中的代码将改回 Visual Studio 呈现的默认值。我该如何处理?@okarpov? (2认同)

sau*_*tel 13

确保你不自动调整列,它可以提高性能.

即不要这样做Datagridview.Columns [I] .AutoSizeMode = DataGridViewAutoSizeColumnMode.xxxxx;


Tec*_*Man 9

通常关闭自动调整大小和双缓冲有助于加速DataGridView填充.检查DGV双缓冲是否正确打开:

if (!System.Windows.Forms.SystemInformation.TerminalServerSession)
{
  Type dgvType = dataGridView1.GetType();
  PropertyInfo pi = dgvType.GetProperty("DoubleBuffered",
    BindingFlags.Instance | BindingFlags.NonPublic);
  pi.SetValue(dataGridView1, value, null);
}
Run Code Online (Sandbox Code Playgroud)

使用WinAPI WM_SETREDRAW消息禁用重绘也有助于:

// *** API Declarations ***
[DllImport("user32.dll")]
private static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wParam, Int32 lParam);
private const int WM_SETREDRAW = 11;

// *** DataGridView population ***
SendMessage(dataGridView1.Handle, WM_SETREDRAW, false, 0);
// Add rows to DGV here
SendMessage(dataGridView1.Handle, WM_SETREDRAW, true, 0);
dataGridView1.Refresh();
Run Code Online (Sandbox Code Playgroud)

如果您不需要双向数据绑定或BindingSource提供的某些功能(过滤等),您可以考虑使用DataGridView.Rows.AddRange()方法一次添加行.

链接到源文章的示例:http://10tec.com/articles/why-datagridview-slow.aspx


squ*_*les 6

我必须在一些地方禁用自动调整大小才能看到性能的最大改进。就我而言,我为AutoSizeRowsModeAutoSizeColumnsMode和启用了自动调整大小模式ColumnHeadersHeightSizeMode。因此,在将数据绑定到以下之前,我必须禁用其中的每一个DataGridView

dataGridView.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None;
dataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;

// ... Bind the data here ...

// Set the DataGridView auto-size modes back to their original settings.
dataGridView.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;
dataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
Run Code Online (Sandbox Code Playgroud)


Bob*_*y L 5

我知道我参加聚会的时间很晚,但是最近我对DataGridView控件的自动调整大小太慢感到厌烦,并且觉得有人可能会从我的解决方案中受益。

我创建了这种扩展方法,用于手动测量和调整DataGridView中的列的大小。将AutoSizeColumnsMode设置为DataGridViewAutoSizeColumnsMode.None并在设置DataSource后调用此方法。

/// <summary>
/// Provides very fast and basic column sizing for large data sets.
/// </summary>
public static void FastAutoSizeColumns(this DataGridView targetGrid)
{
    // Cast out a DataTable from the target grid datasource.
    // We need to iterate through all the data in the grid and a DataTable supports enumeration.
    var gridTable = (DataTable)targetGrid.DataSource;

    // Create a graphics object from the target grid. Used for measuring text size.
    using (var gfx = targetGrid.CreateGraphics())
    {
        // Iterate through the columns.
        for (int i = 0; i < gridTable.Columns.Count; i++)
        {
            // Leverage Linq enumerator to rapidly collect all the rows into a string array, making sure to exclude null values.
            string[] colStringCollection = gridTable.AsEnumerable().Where(r => r.Field<object>(i) != null).Select(r => r.Field<object>(i).ToString()).ToArray();

            // Sort the string array by string lengths.
            colStringCollection = colStringCollection.OrderBy((x) => x.Length).ToArray();

            // Get the last and longest string in the array.
            string longestColString = colStringCollection.Last();

            // Use the graphics object to measure the string size.
            var colWidth = gfx.MeasureString(longestColString, targetGrid.Font);

            // If the calculated width is larger than the column header width, set the new column width.
            if (colWidth.Width > targetGrid.Columns[i].HeaderCell.Size.Width)
            {
                targetGrid.Columns[i].Width = (int)colWidth.Width;
            }
            else // Otherwise, set the column width to the header width.
            {
                targetGrid.Columns[i].Width = targetGrid.Columns[i].HeaderCell.Size.Width;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

虽然我当然不建议使用1000多个行来填充DGV,但是这种方法在产生与AutoResizeColumns方法非常相似的结果的同时,还能带来巨大的性能优势。

对于1万行:(1万行* 12列。)

AutoResizeColumns = 〜3000毫秒

FastAutoSizeColumns = 〜140毫秒

  • 我意识到我晚了近两年才发表评论,但只是想说这确实帮助了我。 (2认同)