tags:

views:

3881

answers:

6

In my application I have a DataGridView control that displays data for the selected object. When I select a different object (in a combobox above), I need to update the grid. Unfortunately different objects have completely different data, even different columns, so I need to clear all the existing data and columns, create new columns and add all the rows. When this is done, the whole control flickers horribly and it takes ages. Is there a generic way to get the control in an update state so it doesn't repaint itself, and then repaint it after I finish all the updates?

It is certainly possible with TreeViews:

myTreeView.BeginUpdate();
try
{
    //do the updates
}
finally
{
    myTreeView.EndUpdate();
}

Is there a generic way to do this with other controls, DataGridView in particular?

UPDATE: Sorry, I am not sure I was clear enough. I see the "flickering", because after single edit the control gets repainted on the screen, so you can see the scroll bar shrinking, etc.

A: 

Sounds like you want double-buffering:

http://www.codeproject.com/KB/graphics/DoubleBuffering.aspx

Although this is mainly used for individual controls, you can implement this in your Windows Forms control or Form.

DannySmurf
I tried double-buffering, but it didn't help much. I think the issue is that it tries to repaint after every row I add, so it ends up updating the first rows multiple times.
Grzenio
+1  A: 

Unfortunatly, I think that thins might just be a by-product of the .net framework. I am experiencing similar flickering albeit with custom controls. Many of the reference material I have read indicates this, alongside the fact the the double buffering method failed to remove any flickering for me.

TK
+2  A: 

Double buffering won't help here since that only double buffers paint operations, the flickering the OP is seeing is the result of multiple paint operations:

  • Clear control contents -> repaint
  • Clear columns -> repaint
  • Populate new columns -> repaint
  • Add rows -> repaint

so that's four repaints to update the control, hence the flicker. Unfortunately, not all the standard controls have the BeginUpdate/EndUpdate which would remove all the repaint calls until the EndUpdate is called. Here's what you can do:

  1. Have a different control for each data set and Show/Hide the controls,
  2. Remove the control from its parent, update and then add the control again,
  3. Write your own control.

Options 1 and 2 would still flicker a bit.

On the .Net GUI program I'm working on, I created a set of custom controls that eliminated all flicker.

Skizz

Skizz
Yeah, I am pretty sure this is exactly the problem. And because I have to add >50 rows, you can see how the grid is growing. When you created your controls, you extended the existing data grid view, or wrote a new one from scratch?
Grzenio
I wrote them from scratch, derived from UserControl and they are all very application specific.
Skizz
+2  A: 

The .NET control supports the SuspendLayout and ResumeLayout methods. Pick the appropriate parent control (i.e. the control that hosts the controls you want to populate) and do something like the following:

this.SuspendLayout();

// Do something interesting.

this.ResumeLayout();
Ken Wootton
Yeah, I tried it but it just doesn't work :(
Grzenio
+3  A: 

Rather than adding the rows of the data grid one at a time, use the DataGridView.Rows.AddRange method to add all the rows at once. That should only update the display once. There's also a DataGridView.Columns.AddRange to do the same for the columns.

Skizz

Skizz
Cheers, this seems the best you can get with DataGridView
Grzenio
A: 

This worked for me.

http://www.syncfusion.com/faq/windowsforms/search/558.aspx

Basically it involves deriving from the desired control and setting the following styles.

SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true); 
SetStyle(ControlStyles.DoubleBuffer, true);
Brian Hasden