1

The datagridview is loading very slowly. How can I optimise it?

The datagridview has 4-5 thousand rows.
I have to generate a datagridview dynamically on a few parameters.(Data from database, No. of columns)

I have to generate the datagridview like this vertically from the table (id,name,contact) in database..

Column1

id
name
contact

Now there can be any number of more empty columns beside column1.

Currently I am following this approach.

  1. First adding all the empty columns.
  2. Then adding three rows in each for loop iteration one row for each (id,name,contact).
  3. I am fetching the data from the database and passing it as a List <string[]> to the GenerateRows function.

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

I was thinking to make a procedure in sql which will create a table and fill it with the data. Then just assign the datasource to the datagridview.

  • Why would you load 4-5 thousand rows? How often does a user actually inspect 4-5 thousand rows. If three columns and can read every cell in 1 second that is still over 3 hours to read. Page in 100 or 1000 rows at a time. – paparazzo Jul 09 '13 at 17:59
  • I have to create this type of datagrid because data entry work will be done from this grid. –  Jul 09 '13 at 18:04
  • This will be a very tedious task for the data entry operator. –  Jul 09 '13 at 18:06
  • Really a 4 thousand row datagridview is your only option for data entry. And loading very slowly is not a tedious task for the data entry operator? – paparazzo Jul 09 '13 at 18:13
  • Only those data which they are having in hand in their reports will be filled. So I do not know which records will be filled. And so I have to show all the records. Then the full datagrid will be printed. Even the empty cells. For handwritten data entry of the left out work –  Jul 09 '13 at 18:17
  • Still, 4 thousand row datagridview is not your only option. And I serious doubt it is you best option. – paparazzo Jul 09 '13 at 18:40
  • I know that it is not the best option but if I cannot improve the performance then I will divide it into smaller parts similar to pagination. I will try the below given advice and will also see if creating such table in database and assigning it as a datasource will work or not. –  Jul 09 '13 at 18:45

3 Answers3

2

What I did is instead of adding rows one by one to the DataGridView. I just created a DataTable from my data and assigned it as a DataSource to the DataGridView.

The performance of loading the DataGridView improved significantly.

  • you have specified that you are adding rows manually, so i assumed that you dont want to use DataBinding. else this would have been my answer. There are even more optimized ways in DataBinding to suspend data update. – Sriram Sakthivel Jul 12 '13 at 08:59
  • i had 20,000 rows in the DataTable and tried to assign to data source of datagridview and it was extremely slow – PUG Dec 13 '13 at 20:06
1

The problem is that Datagridview repaints whenever you add a row to it, if you don't mind to use P/Invoke you can try this solution //to suspend paint

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

//Your loop to add rows here

then call below method to resume painting

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

and the P/Invoke declaration should be something like this

[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;
Matthew Lock
  • 13,144
  • 12
  • 92
  • 130
Sriram Sakthivel
  • 72,067
  • 7
  • 111
  • 189
0

Calling Rows.Add() is expensive. This is a quick-and-dirty change to get around that.

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());
}
Ria
  • 10,237
  • 3
  • 33
  • 60
Greg
  • 16,540
  • 9
  • 51
  • 97
  • What will be better to suspend paint when adding rows or to use addrange. Or should I use both at the same time. i.e suspend paint and addrange. –  Jul 09 '13 at 18:19
  • This seems easier to me, but you could try each and see what you like better. – Greg Jul 09 '13 at 18:38