17

How can I suspend a .NET DataGridView from displaying anything while I update its Columns?

Here's my current code. It works ok, but it is very slow on the foreach loop; you can see the horiz scroll bar grow slowly as each column is added. I'm building the UI columns myself as I do not want to use dataGridView1.AutoGenerateColumns for various reasons.

// Disconnect and reset DataGridView
dataGridView1.DataSource = null;
dataGridView1.SuspendLayout();
dataGridView1.Columns.Clear();

// Get data from SQL
DataTable dt = new DataTable();
SqlDataAdapter adapter = new SqlDataAdapter("select * from employeehist", conn);
adapter.Fill(dt);

// Build DataGridView columns
foreach (DataColumn c in dt.Columns)
{
    DataGridViewTextBoxColumn col = new DataGridViewTextBoxColumn();
    col.SortMode = DataGridViewColumnSortMode.NotSortable;
    col.DataPropertyName = c.ColumnName;
    col.HeaderText = c.Caption;
    dataGridView1.Columns.Add(col);
}

// Reconnect DataGridView
dataGridView1.DataSource = dt;
dataGridView1.ResumeLayout(true);
Lane
  • 2,669
  • 3
  • 25
  • 38
  • Hmm. That should do it... Try placing `dataGridView1.DataSource = null` after the SuspendLayout call? Do you expect the columns to change between two requests? If not, you might want to remove column creation from this method entirely. – Adam Lear Jan 10 '11 at 18:27
  • Yes, the column count can change. The queried result set can vary depending on a date range the user selects. Also, tried moving the ' = null' and it didn't help. Thanks though, – Lane Jan 10 '11 at 20:43
  • @Lane, I have the same problem, but not the datagridview. I am using GridView to bind data, and during the loop, it's extremely slow, and GridView doesn't have Columns.AddRange function...wondering why and how did you fix for your case? Thanks. – Princa Nov 22 '13 at 20:15

7 Answers7

4

In my case suspend and resume layout did not work. I resolved disabling the dataGridView (dgv.Enabled = false) before update and re-enabling it (dgv.Enabled = true) at the end of the update process.

Zac
  • 4,510
  • 3
  • 36
  • 44
  • Another useful approach can be found here: http://stackoverflow.com/questions/1550293/stopping-textbox-flicker-during-update Look for LockWindowUpdate... – mike Oct 31 '16 at 23:57
4

You can use VirtualMode with DataGridView in order to very efficiently update the grid. See this article: http://msdn.microsoft.com/en-us/library/ms171622.aspx

From what I remember, it seems to update the entire collection before updating anything on the UI, as opposed to adding to the UI for each new row added/etc.

ferr
  • 1,137
  • 3
  • 12
  • 28
  • Here is a walkthrough: http://msdn.microsoft.com/en-us/library/15a31akc.aspx It takes a little more work to set it up, but it should be much faster once implemented. – ferr Jan 10 '11 at 18:34
4

You may want to consider using the AddRange method instead of Add. The Data Grid behaves a little better when you add them all at once.

DataGridViewColumn[] columns = new DataGridViewColumn[dt.Columns.Count];

for (int i = 0; i < dt.Columns.Count; i++ )
{
    DataColumn c = dt.Columns[i];
    DataGridViewTextBoxColumn col = new DataGridViewTextBoxColumn();
    col.SortMode = DataGridViewColumnSortMode.NotSortable;
    col.DataPropertyName = c.ColumnName;
    col.HeaderText = c.Caption;

    columns[i] = col;
}


dataGridView1.Columns.AddRange(columns);
Botea Bogdan
  • 192
  • 3
  • 16
Conrad Frix
  • 51,984
  • 12
  • 96
  • 155
  • 1
    Good idea, but I still have the same exact lag. It lags on one line: dataGridView1.Columns.AddRange(columns); – Lane Jan 10 '11 at 20:12
  • 1
    Also make sure you use insert at the beginning: `dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;` since otherwise, this really slows things down. – Dan W Sep 10 '12 at 03:07
1

You could try and prevent it from completely redrawing by using the code in this post. The parent would be the parent of the dataGridView1.

Community
  • 1
  • 1
SwDevMan81
  • 48,814
  • 22
  • 151
  • 184
  • 2
    I tried this but it didn't help oddly. Drawing was clearly suspended, but I clocked the exact same time. It feels like the DataGridView still draws in the background whether drawing has been suspended or not. – Lane Jan 11 '11 at 20:53
1

Significant performance increase:

var dgv = new DataGridView();
dgv.SuspendLayout();
// Do update, change values
dgv.ResumeLayout();

May not be ultimate high performance.

coarist
  • 789
  • 9
  • 11
1

This will speed it up 10 times.

dataGridView1.Visible = false;
//Build/populate datagridview
dataGridView1.Visible = true;

It's not the most professional approach but it performs.

navigator
  • 1,678
  • 16
  • 29
Neil
  • 11
  • 1
0

If you are using timer then use SynchronizingObject. This removes the flickering completly for me.

var dgv = new DataGridView();
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 1000;
timer.SynchronizingObject = dgv;  // syncronise
timer.Start();
timer.Elapsed += Timer_Elapsed;
void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    refreshDGV();  // in here I refresh the DataGridView
}