4

I have a DataGridView and I fill it like this:

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

My problem is that Rows.Add(cells) is too slow (I have a huge amount of data).

This is an example of the content of 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
...

I would like to use a BindingList and setting it as DataSource, which would make it much faster. The problem is that I don't know the number of columns a priori (in this example is just "TIME,Temperature", but it could be "TIME,Temperature,Rainfall,...,Other").

Xavier Peña
  • 7,399
  • 9
  • 57
  • 99
  • Is the maximum set of columns known ahead of time? If so, have a static datagrid with all those columns and make columns hidden based on the specific data you are binding. You can then create a datasource that has all columns present but only the relevant columns populated with data. – user469104 Apr 21 '16 at 13:15

2 Answers2

5

Don't add the rows to the grid one at a time in a loop. Create all the rows in the loop first and then add them all to the grid with a single call to AddRange.

Alternatively, populate a DataTable or some other suitable list and then bind it to the grid.

If you have so much data that that's still too slow then you may need to look at virtualising the grid.

jmcilhinney
  • 50,448
  • 5
  • 26
  • 46
  • About creating the rows in the loop, I have tried this approach but I found that there was not possible (?) to create rows independently. See these answers: http://stackoverflow.com/a/10063825/831138 <= all these ways to create new DataRows are convoluted and seem to depend on the DataGridView itself. – Xavier Peña Apr 21 '16 at 13:19
  • Wait, it looks like the second suggestion ("Alternatively, populate a DataTable or some other suitable list and then bind it to the grid.") is good enough! Thanks! If other people are looking for the same thing: 1) `var dataTable = new DataTable();`, 2) Add columns to dataTable, 3) `dataTable.Rows.Add(cells);`, and 4) `this.dataGridView.DataSource = dataTable;`. – Xavier Peña Apr 21 '16 at 13:28
  • 1
    For me, AddRange is about 10x faster. The code is only 2x as ugly for filling a list first and calling CreateCells on each row before initializing. – Andreas Reiff Jul 04 '19 at 15:04
0

If you don't want to change your code try to:

  • suspend DataGridView drawing during FillDataGridView
  • resume DataGridView drawing at the end of process

To suspend control drawing you can use this code:

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

To resume control drawing you can use this code:

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

Remember to use a Try/Catch/Finally block in order to prevent problem in case something goes wrong and DataGridView drawing is suspended.

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
tezzo
  • 10,858
  • 1
  • 25
  • 48