Grzenio
Grzenio

Reputation: 36639

Flickering during updates to Controls in WinForms (e.g. DataGridView)

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.

Upvotes: 7

Views: 23884

Answers (8)

Ramgy Borja
Ramgy Borja

Reputation: 2458

You may also try this, its work.

public static void DoubleBuffered(Control formControl, bool setting)
{
    Type conType = formControl.GetType();
    PropertyInfo pi = conType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
    pi.SetValue(formControl, setting, null);
}

Upvotes: 0

Jon
Jon

Reputation: 101

People seem to forget a simple fix for this:

Object.Visible = false;

//do update work

Object.Visible = true;

I know it seems weird, but that works. When the object is not visible, it won't redraw itself. You still, however, need to do the begin and end update.

Upvotes: 10

Skizz
Skizz

Reputation: 71060

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.

Upvotes: 8

Skizz
Skizz

Reputation: 71060

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.

Upvotes: 7

Brian H
Brian H

Reputation: 4110

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

Upvotes: 2

Ken Wootton
Ken Wootton

Reputation: 1110

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

Upvotes: 9

TK.
TK.

Reputation: 47873

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.

Upvotes: 1

TheSmurf
TheSmurf

Reputation: 15568

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.

Upvotes: 1

Related Questions