Sep 27, 2007

How To Create a Flicker Free TableLayoutPanel

The TableLayoutPanel that comes with .NET 2.0 is handy for doing simple HTML style layouts without the hassle of having to embed a browser control in your form and write the HTML.  The control is designed to be a lightweight container (not as powerful as the DataGridView, but more flexible in it's approach) and you can embed any control you like in it.

The main problem however is that the control flickers incredibly badly when it gets resized. 

For windows forms applications the way to remove flickering is to enable double buffering.  For a form you can just set the DoubleBuffered property to true, and while this will reduce flicker when you resize the form itself, the TableLayoutPanels on the form still flicker as they resize.

So to fix this you just need to turn on double buffering for the control.  Unfortunately, the control doesn't feature a "DoubleBuffered" property.

You could try setting the ControlStyles for the control as well, however the SetStyle method is not exposed by the control.

So that means we'll need to use subclassing to set the double buffering flags.  The following C# code shows you a simple double buffered TableLayoutPanel :

using System.ComponentModel;
using System.Windows.Forms;

namespace MyNameSpace
{
/// <summary>
/// Double Buffered layout panel - removes flicker during resize operations.
/// </summary>
public partial class DBLayoutPanel : TableLayoutPanel
{
public DBLayoutPanel()
{
InitializeComponent();
SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.UserPaint, true);
}

public DBLayoutPanel(IContainer container)
{
container.Add(this);
InitializeComponent();
SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.UserPaint, true);
}
}
}

Create the class as shown, rebuild your code and the toolbox should now show you that a DBLayoutPanel control is available for your UI pleasure.


Oh, if you happen to have already built forms using the standard TableLayoutPanel you won't need to delete them and start again.  Just go into the *.Designer.cs code-beside files and change the TableLayoutPanel references to DBLayoutPanel ones (watch your namespaces!).  Rebuild your application and everything should run as it did before, this time without the flickering.

22 comments:

  1. Thanks a lot, really good tip. ALTHOUGH I'm getting compiler errors for the "InitializeComponent();" lines. Any clues? Cheers...
    bleepy

    ReplyDelete
  2. That's a bit unusual. Without seeing the compiler error itself, I'd hazard a guess and say that you've got a missing reference or you're missing a using statement at the top of the code.

    ReplyDelete
  3. This does not solve the problem. The fickering is reduced but it still exists.

    ReplyDelete
  4. What you may be seeing is flickering associated with other controls and you may also be coming up against the limitations of WinForms apps in general. I don't know that you'll get much improvement on what you see unless you move to WPF.

    The way WinForms apps are painted on the screen is not ideal and under any sort of CPU load you will likely see some flicker (though not much) and occasionally even some graphics artifacts.

    WPF apps won't exhibit this behaviour as the drawing to the screen is handled by the graphics cards and the DirectX framework. In WinForms we're not so lucky and have to make do with what we have.

    ReplyDelete
  5. There is another solution:

    public partial class DBLayoutPanel : TableLayoutPanel {
    public DBLayoutPanel()
    {
    this.DoubleBuffered = true;
    }
    }

    This will avoid flickering at all.

    ReplyDelete
  6. Thanks for the tip with the DoubleBuffering.

    I wondered why painting a table with some labels should flicker.

    PS: Since .NET 2.0 you can set the DoubleBuffering value directly, like this:

    public MyLayoutPanel : TableLayoutPanel{

    public MyLayoutPanel( ){
    this.DoubleBuffered = true;
    }

    }

    ReplyDelete
  7. This was cool. I personally do not know how but this tip fixed my problem. Thank You,

    Ashish Raje

    ReplyDelete
  8. Thank you very much!

    ReplyDelete
  9. A nice trick. Thank you.

    ReplyDelete
  10. Worked like a charm. Thanks for post.

    ReplyDelete
  11. Magnificent. Thanks dude.

    ReplyDelete
  12. For anyone listening out there...

    I did all this and it reduced the flicker a great deal when the form loaded - but the flicker still existed when I added any new controls (labels) or if there were a lot of rows (>20)...

    My solution: Make sure the CellBorderStyle is set to None. If you want lines, use the borders on the controls themselves. That did the trick for me.

    ReplyDelete
  13. I too had the same problem and Richard's solution worked perfectly well for me. Thank you so much!

    ReplyDelete
  14. If you get compiler errors about InitializeComponent() missing, you have to add a new item from templates "Windows Forms/Custom Control", and not "class" or whatever.

    ReplyDelete
  15. Thanks a lot to all. I have a 100% flicker-free tablelayoutpanel in Winforms.

    ReplyDelete
  16. Brilliant. Solved our bad flickering issue. Thanks

    ReplyDelete
  17. I had to do the same trick for containing and nested Panels, too; but it helped a great deal. Thanks! Matthias

    ReplyDelete
  18. Thanks a Zillion..:) was having a difficult time since it is not the same if one is using Panel and the instructions were for Panel Class.

    ReplyDelete
  19. Mikael FredrikssonNov 12, 2011, 3:34:00 AM

    Thank you! I've been looking for a way to solve this for ages.

    ReplyDelete
  20. Thanks a lot! finally got fixed

    ReplyDelete
  21. You have won free beer from me for life - I was almost on the verge of topping myself over this problem (having designed a program for 8 months night and day solid, I came up against a 'flicker' wall which I thought was insurmountable). Well done and thanks again - brilliant solution

    ray_chapman48@hotmail.com

    ReplyDelete
  22. This made my day! I had layers of controls in my form (panels, TableLayoutPanels, labels) and had no clue what was causing the flickering. I gave your solution a try because it was so easy and neat. Bingo! It worked like a charm! Thank you so much for a beautiful solution to a frustrating problem.

    ReplyDelete