【问题标题】:The DataGridView is loading very slowly. How to optimise adding of rows in DataGridView?DataGridView 加载非常缓慢。如何优化 DataGridView 中行的添加?
【发布时间】:2013-07-07 10:34:36
【问题描述】:

datagridview 加载非常缓慢。如何优化它?

datagridview 有 4-5 千行。
我必须在几个参数上动态生成一个datagridview。(来自数据库的数据,列数)

我必须从数据库中的表(id,name,contact)垂直生成这样的datagridview..

第 1 列

id
姓名
联系人

现在,column1 旁边可以有任意数量的空列。

目前我正在遵循这种方法。

  1. 首先添加所有空列。
  2. 然后在每个 for 循环迭代中添加三行,每个 (id,name,contact) 一行。
  3. 我正在从数据库中获取数据并将其作为List <string[]> 传递给GenerateRows 函数。

     private void GenerateColumns(int colLen)
        {
            dataGridViewGenerate.Rows.Clear();
            dataGridViewGenerate.Columns.Clear();
    
            DataGridViewColumn col0 = new DataGridViewTextBoxColumn();
            col0.HeaderText = "Employee No. & Name";
            dataGridViewGenerate.Columns.Add(col0);
    
            for (int i = 0; i < colLen; i++)
            {
                DataGridViewColumn col = new DataGridViewTextBoxColumn
                    {
                        HeaderText =
                            (_sTime.AddDays(i)).Day.ToString(CultureInfo.InvariantCulture) + " " +
                            (_sTime.AddDays(i)).ToString("ddd")
                    };
    
                dataGridViewGenerate.Columns.Add(col);
        }
    
    
    private void GenerateRows(List<string[]> empList)
        {
            int len = empList.Count;
            for (int a = 0; a < len; a++)
            {
                string[] arr = empList[a];
                //row 1
                var row1 = new DataGridViewRow();
                row1.Cells.Add(new DataGridViewTextBoxCell
                    {
                        Value = arr[0]
                    });
                dataGridViewGenerate.Rows.Add(row1);
    
                //row 2
                var row2 = new DataGridViewRow();
                row2.Cells.Add(new DataGridViewTextBoxCell
                    {
                        Value = arr[1]
                    });
                dataGridViewGenerate.Rows.Add(row2);
    
                //row3
    
                var row3 = new DataGridViewRow();
                row3.Cells.Add(new DataGridViewTextBoxCell
                    {
                        Value = arr[2]
                    });
                dataGridViewGenerate.Rows.Add(row3);
            }
        }
    

我正在考虑在 sql 中创建一个过程,该过程将创建一个表并用数据填充它。然后只需将数据源分配给 datagridview。

【问题讨论】:

  • 为什么要加载 4-5 千行?用户实际检查 4-5 千行的频率。如果三列并且可以在 1 秒内读取每个单元格,那么读取时间仍然超过 3 小时。一次分页 100 或 1000 行。
  • 我必须创建这种类型的数据网格,因为数据输入工作将从这个网格完成。
  • 这对于数据输入操作员来说将是一项非常繁琐的工作。
  • 真正的 4000 行数据网格视图是您输入数据的唯一选择。而且加载很慢对数据录入操作员来说不是一件乏味的工作吗?
  • 只会填写他们手头的报告中的数据。所以我不知道会填写哪些记录。所以我必须展示所有的记录。然后将打印完整的数据网格。甚至是空的牢房。用于遗漏工作的手写数据输入

标签: c# .net database datagridview


【解决方案1】:

调用 Rows.Add() 很昂贵。这是一个快速而肮脏的改变来解决这个问题。

private void GenerateRows(List<string[]> empList)
{
    List<DataGridViewRow> rows = new List<DataGridViewRow>();
    int len = empList.Count;
    for (int a = 0; a < len; a++)
    {
        string[] arr = empList[a];
        //row 1
        var row1 = new DataGridViewRow();
        row1.Cells.Add(new DataGridViewTextBoxCell{Value = arr[0]});
        /* CHANGED to add to List */
        rows.Add(row1);

        //row 2
        var row2 = new DataGridViewRow();
        row2.Cells.Add(new DataGridViewTextBoxCell{Value = arr[1]});
        /* CHANGED to add to List */
        rows.Add(row2);

        //row3

        var row3 = new DataGridViewRow();
        row3.Cells.Add(new DataGridViewTextBoxCell{Value = arr[2]});
        /* CHANGED to add to List */
        rows.Add(row3);
    }

    /* ADDED all rows at once for performance */
    dataGridViewGenerate.Rows.AddRange(rows.ToArray());
}

【讨论】:

  • 在添加行或使用 addrange 时暂停绘制会更好。或者我应该同时使用两者。即暂停油漆和添加范围。
  • 这对我来说似乎更容易,但你可以尝试每一个,看看你更喜欢什么。
【解决方案2】:

问题是,每当您向其中添加一行时,Datagridview 都会重新绘制, 如果你不介意使用 P/Invoke,你可以试试这个解决方案 //暂停绘画

SendMessage(Datagridview.Handle, WM_SETREDRAW, false, 0);

//你的循环在这里添加行

然后调用下面的方法继续绘画

SendMessage(Datagridview.Handle, WM_SETREDRAW, true, 0);

P/Invoke 声明应该是这样的

[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wParam, Int32 lParam);
private const int WM_SETREDRAW = 0x000B;

【讨论】:

  • 我必须在 WM_SETREDRAW 之后调用 Datagridview.Refresh() 才能使网格看起来完全绘制
【解决方案3】:

我所做的不是将行一一添加到DataGridView。我刚刚从我的数据中创建了一个DataTable,并将其作为DataSource 分配给DataGridView

加载DataGridView 的性能显着提高。

【讨论】:

  • 您已指定手动添加行,因此我假设您不想使用 DataBinding。否则这将是我的答案。 DataBinding 中还有更优化的方式来暂停数据更新。
  • 我在 DataTable 中有 20,000 行,并试图分配给 datagridview 的数据源,它非常慢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多