17

We had a performance issue with DataGridViews where the redraw was horridly slow and found the solution Here to create a derived type and enable double buffering on the control. (Derived type is necessary since the DoubleBuffered property is protected)

It doesn't seem like there's any drawback to having the DoubleBuffered property set to true.

Community
  • 1
  • 1
Karg
  • 1,467
  • 3
  • 15
  • 18

4 Answers4

25

I think its best solution:

typeof(DataGridView).InvokeMember(
   "DoubleBuffered", 
   BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty,
   null, 
   myDataGridViewObject, 
   new object[] { true });

found here

Community
  • 1
  • 1
Dawid Moś
  • 827
  • 2
  • 12
  • 18
21

It is protected because DGV inherits the property from Control. And Control.DoubleBuffered is protected. Which makes sense because each derived control should decide for itself to turn that on. And it doesn't make sense for the control user to arbitrarily turn it on or off. The DGV designers decided for off.

One reason they might have decided that is that double buffering actually makes painting slower. The extra step to render the buffer bitmap costs time. It just looks faster to the human eye, you observe the bitmap suddenly appearing. You can't see the time it takes to draw into the bitmap. Unless other controls need to be painted and they get their turn after the DGV, then it is quite visible.

What you see is the form getting drawn first, with holes where the controls go. Those holes have a white background. Black when you use the TransparencyKey or Opacity property. Each control then gets the Paint event and the holes are filled one-by-one. That effect is perceived as flicker too by the user, although it is a different kind of flicker from the one that DoubleBuffered solves. It is especially noticeable when the background is black.

What's needed to solve this problem is that the entire form, with all its controls, is double-buffered. That's not available in Windows Forms. However, Windows XP and later actually support this, they called it "compositing". Copy/paste this code anywhere in the form class:

protected override CreateParams CreateParams {
    get {
        CreateParams cp = base.CreateParams;
        cp.ExStyle |= 0x02000000;  // Turn on WS_EX_COMPOSITED
        return cp;
    }
}
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Interesting, though in the case of the datagridview, without doublebuffering, it takes 2-3 seconds to redraw the control, but with double buffering, it appears instant – Karg Nov 03 '08 at 16:28
  • btw, up vote for the answer to the protected portion of the question – Karg Nov 03 '08 at 16:32
  • 3
    Actually double buffering makes it significantly faster... enough faster that the naked eye can easily tell the difference. I do appreciate this answer in that it may be the most 'correct' thing to do, but it's not nearly as practical as just using reflection to set change the setting on the DataGridView – Brandon Moore Jun 18 '13 at 22:53
  • My problem is that when I change my form to use this derived class instead of the normal one that the resource editor will not display the form anymore. – Andrew Truckle Jun 07 '16 at 20:39
5

Double buffering by definition uses two buffers and twice the memory for rendering the view of the control into. So, there is some drawback there, however, with the amount of memory you get in a PC now, not many people probably would notice the sacrifice.

No idea why its protected. Maybe the function wasn't available in an early version of the control, and when it was introduced the designers didn't want to change the public interface of the control. Or perhaps they considered it to be an advanced feature and wanted to limit the number of methods someone new to the control would have to grok to be able to make it do something useful.

Scott Langham
  • 58,735
  • 39
  • 131
  • 204
4

Inheritance is not needed to turn on doublebuffering on a datagridview. You can do it with reflection on an existing datagridview.