How to prevent flicker in ListView when updating single ListViewItem text?

All I want to do is update the ListViewItem text without visible flicker.

This is my update code (called several times):

listView.BeginUpdate(); listViewItem.SubItems[0].Text = state.ToString(); // update the state listViewItem.SubItems[1].Text = progress.ToString(); // update the progress listView.EndUpdate(); 

I saw some solutions that include overriding the WndProc(): component WndProc():

 protected override void WndProc(ref Message m) { if (m.Msg == (int)WM.WM_ERASEBKGND) { m.Msg = (int)IntPtr.Zero; } base.WndProc(ref m); } 

It is said that this solves the problem, but in my case it is not . I believe this is because I use icons for each item.

+41
c # listview winforms
Sep 17 '08 at 21:21
source share
10 answers

To end this question, here is a helper class that should be called when the form loads for each ListView or any other ListView control in your form. Thanks to Brian Gillespie for providing the solution.

 public enum ListViewExtendedStyles { /// <summary> /// LVS_EX_GRIDLINES /// </summary> GridLines = 0x00000001, /// <summary> /// LVS_EX_SUBITEMIMAGES /// </summary> SubItemImages = 0x00000002, /// <summary> /// LVS_EX_CHECKBOXES /// </summary> CheckBoxes = 0x00000004, /// <summary> /// LVS_EX_TRACKSELECT /// </summary> TrackSelect = 0x00000008, /// <summary> /// LVS_EX_HEADERDRAGDROP /// </summary> HeaderDragDrop = 0x00000010, /// <summary> /// LVS_EX_FULLROWSELECT /// </summary> FullRowSelect = 0x00000020, /// <summary> /// LVS_EX_ONECLICKACTIVATE /// </summary> OneClickActivate = 0x00000040, /// <summary> /// LVS_EX_TWOCLICKACTIVATE /// </summary> TwoClickActivate = 0x00000080, /// <summary> /// LVS_EX_FLATSB /// </summary> FlatsB = 0x00000100, /// <summary> /// LVS_EX_REGIONAL /// </summary> Regional = 0x00000200, /// <summary> /// LVS_EX_INFOTIP /// </summary> InfoTip = 0x00000400, /// <summary> /// LVS_EX_UNDERLINEHOT /// </summary> UnderlineHot = 0x00000800, /// <summary> /// LVS_EX_UNDERLINECOLD /// </summary> UnderlineCold = 0x00001000, /// <summary> /// LVS_EX_MULTIWORKAREAS /// </summary> MultilWorkAreas = 0x00002000, /// <summary> /// LVS_EX_LABELTIP /// </summary> LabelTip = 0x00004000, /// <summary> /// LVS_EX_BORDERSELECT /// </summary> BorderSelect = 0x00008000, /// <summary> /// LVS_EX_DOUBLEBUFFER /// </summary> DoubleBuffer = 0x00010000, /// <summary> /// LVS_EX_HIDELABELS /// </summary> HideLabels = 0x00020000, /// <summary> /// LVS_EX_SINGLEROW /// </summary> SingleRow = 0x00040000, /// <summary> /// LVS_EX_SNAPTOGRID /// </summary> SnapToGrid = 0x00080000, /// <summary> /// LVS_EX_SIMPLESELECT /// </summary> SimpleSelect = 0x00100000 } public enum ListViewMessages { First = 0x1000, SetExtendedStyle = (First + 54), GetExtendedStyle = (First + 55), } /// <summary> /// Contains helper methods to change extended styles on ListView, including enabling double buffering. /// Based on Giovanni Montrone article on <see cref="http://www.codeproject.com/KB/list/listviewxp.aspx"/> /// </summary> public class ListViewHelper { private ListViewHelper() { } [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern int SendMessage(IntPtr handle, int messg, int wparam, int lparam); public static void SetExtendedStyle(Control control, ListViewExtendedStyles exStyle) { ListViewExtendedStyles styles; styles = (ListViewExtendedStyles)SendMessage(control.Handle, (int)ListViewMessages.GetExtendedStyle, 0, 0); styles |= exStyle; SendMessage(control.Handle, (int)ListViewMessages.SetExtendedStyle, 0, (int)styles); } public static void EnableDoubleBuffer(Control control) { ListViewExtendedStyles styles; // read current style styles = (ListViewExtendedStyles)SendMessage(control.Handle, (int)ListViewMessages.GetExtendedStyle, 0, 0); // enable double buffer and border select styles |= ListViewExtendedStyles.DoubleBuffer | ListViewExtendedStyles.BorderSelect; // write new style SendMessage(control.Handle, (int)ListViewMessages.SetExtendedStyle, 0, (int)styles); } public static void DisableDoubleBuffer(Control control) { ListViewExtendedStyles styles; // read current style styles = (ListViewExtendedStyles)SendMessage(control.Handle, (int)ListViewMessages.GetExtendedStyle, 0, 0); // disable double buffer and border select styles -= styles & ListViewExtendedStyles.DoubleBuffer; styles -= styles & ListViewExtendedStyles.BorderSelect; // write new style SendMessage(control.Handle, (int)ListViewMessages.SetExtendedStyle, 0, (int)styles); } } 
+51
Oct 02 '08 at 14:55
source share

The accepted answer works, but rather long, and based on the control (as mentioned in other answers), just turning on double buffering is also a bit overkill. But, fortunately, we have a reflection and can also call internal methods if we like (but do not forget what you do!).

Encapsulating this approach in an extension method, we get a fairly short class:

 public static class ControlExtensions { public static void DoubleBuffering(this Control control, bool enable) { var method = typeof(Control).GetMethod("SetStyle", BindingFlags.Instance | BindingFlags.NonPublic); method.Invoke(control, new object[] { ControlStyles.OptimizedDoubleBuffer, enable }); } } 

What can be easily called in our code:

 myListView.DoubleBuffering(true); 

And all the flicker disappeared.

Update

I stumbled upon this question , and because of this, the extension method should (possibly) be better:

 public static void DoubleBuffered(this Control control, bool enable) { var doubleBufferPropertyInfo = control.GetType().GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic); doubleBufferPropertyInfo.SetValue(control, enable, null); } 
+52
Mar 07 '13 at 10:11
source share

ListView in CommonControls 6 (XP or later) supports double buffering. Fortunately, .NET wraps the latest CommonControls on the system. To enable double buffering, send the appropriate Windows message to the ListView control.

Here are the details: http://www.codeproject.com/KB/list/listviewxp.aspx

+11
Sep 19 '08 at 17:22
source share

In .NET Winforms 2.0, there is a protected DoubleBuffered property.

Inheriting a ListView, you can set this protected property to true. This will allow you to use double buffering without having to call SendMessage.

Setting the DoubleBuffered property is similar to setting the following style:

 listview.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true); 

http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=94096

+9
Oct 07 '10 at 23:35
source share

I know this question is pretty old, but since this is one of the first Google search results, I wanted to share my fix.

The only way to remove 100% flicker was to combine the response with Oliver (double buffered extension class) and use the BeignUpdate() and EndUpdate() methods.

None of those who, at their discretion, could not flicker for me. Of course, I use a very complex list, which I need to click on the list and also update it almost every second.

+2
Apr 03 '15 at 19:58
source share

this will help:

 class DoubleBufferedListView : System.Windows.Forms.ListView { public DoubleBufferedListView() :base() { this.DoubleBuffered = true; } } 
+1
Apr 27 2018-12-12T00:
source share

If you only want to update the text, just set the changed SubItem text directly, and not update the entire ListViewItem (you did not say how you are doing your updates).

Overriding that you show is equivalent to simply overriding OnPaintBackground, which would be a “more correct” way to accomplish this task, and this will not help for any element.

If you still have problems, we need to clarify what you actually tried.

0
Sep 17 '08 at 21:26
source share

This is a shot in the dark, but you can try double buffering the control.

 SetStyle( ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.DoubleBuffer, true) 
0
Sep 17 '08 at 21:27
source share

Call the BeginUpdate () method in the ListView before setting up any of the list items, and then call EndUpdate () after all the items have been added.

This will stop the flicker.

0
Sep 18
source share

A simple solution is the following:

yourlistview.BeginUpdate ()

// Make your update adding and removing an item from the list

yourlistview.EndUpdate ()

0
Aug 20 '14 at
source share



All Articles