C# Tip Article
How to prevent flicker in WinForms Control
If you frequently update the content of a WinForms Control, you might observe a flicker issue. This flicker issue often occurs when the content data is large.
Take this example. The code below has a listview that shows file list of System32 folder and it updates a listview column every second. If you run this code, you will likely observe a flicker issue in the ListView control.
private void Form1_Load(object sender, EventArgs e) { //listView1.DoubleBuffered(true); string currDir = @"C:\Windows\System32"; DirectoryInfo di = new DirectoryInfo(currDir); FileInfo[] files = di.GetFiles(); listView1.BeginUpdate(); listView1.View = View.Details; foreach (var fi in files) { ListViewItem lvi = new ListViewItem(fi.Name); lvi.SubItems.Add(""); listView1.Items.Add(lvi); } listView1.Columns.Add("Filename", 100, HorizontalAlignment.Left); listView1.Columns.Add("Comment", 100, HorizontalAlignment.Left); listView1.EndUpdate(); Timer timer1 = new Timer(); timer1.Interval = 1000; timer1.Tick += (s,ea) => { listView1.BeginUpdate(); for (int i = 0; i < listView1.Items.Count; i++) { listView1.Items[i].SubItems[1].Text = DateTime.Now.Second.ToString(); } listView1.EndUpdate(); }; timer1.Enabled = true; }
One way of solving this flicker issue is to use so-called double buffering. Double buffering is using secondary buffer to prevent flicker.
In WinForms, Form class has a public property called "DoubleBuffered", but it only applied to the Form itself and does not apply to child controls. In Control class, there is "DoubleBuffered" property but it is a protected property. So in order to use the protected property, you either have to create a subclass or access the property using some other methods such as reflection.
public class Control { //...(elided).... // Summary: // Gets or sets a value indicating whether this control should redraw its surface // using a secondary buffer to reduce or prevent flicker. // // Returns: // true if the surface of the control should be drawn using double buffering; otherwise, // false. protected virtual bool DoubleBuffered { get; set; } }
Sometimes subclassing makes sense but in many cases using reflection might be easier. Here is an extension method that uses .NET reflection to update "DoubleBuffered" property.
public static class Extensions { public static void DoubleBuffered(this Control control, bool enabled) { var prop = control.GetType().GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic); prop.SetValue(control, enabled, null); } }
Once the extension method is written, then we can call this method once in the program. (In the example above, uncomment this code at the top of Form1_Load)
listView1.DoubleBuffered(true);
This double buffering can be applied to other controls in WinForms.