¿Cómo evitar el parpadeo en ListView al actualizar un solo texto de ListViewItem?

Todo lo que quiero es actualizar el texto de ListViewItem sin ver ningún parpadeo.

Este es mi código para actualizar (llamado varias veces):

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

He visto algunas soluciones que implican anular el componente WndProc():

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

Dicen que resuelve el problema, pero en mi caso no . Creo que esto se debe a que estoy usando íconos en cada ítem.

La respuesta aceptada funciona, pero es bastante larga, y derivar del control (como se menciona en las otras respuestas) solo para habilitar el doble almacenamiento en memoria también es un poco exagerado. Pero afortunadamente tenemos un reflection y también podemos llamar a métodos internos si queremos (¡pero asegúrese de lo que hace!).

Al encapsular este enfoque en un método de extensión, obtendremos una clase bastante corta:

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

Que se puede llamar fácilmente dentro de nuestro código:

 myListView.DoubleBuffering(true); 

Y todo parpadeo se ha ido.

Actualizar

Me tropecé con esta pregunta y debido a este hecho, el método de extensión debería (tal vez) ser mejor:

 public static void DoubleBuffered(this Control control, bool enable) { var doubleBufferPropertyInfo = control.GetType().GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic); doubleBufferPropertyInfo.SetValue(control, enable, null); } 

Para finalizar esta pregunta, aquí hay una clase de ayuda a la que se debe llamar cuando se carga el formulario para cada ListView o cualquier otro control derivado de ListView en su formulario. Gracias a “Brian Gillespie” por dar la solución.

 public enum ListViewExtendedStyles { ///  /// LVS_EX_GRIDLINES ///  GridLines = 0x00000001, ///  /// LVS_EX_SUBITEMIMAGES ///  SubItemImages = 0x00000002, ///  /// LVS_EX_CHECKBOXES ///  CheckBoxes = 0x00000004, ///  /// LVS_EX_TRACKSELECT ///  TrackSelect = 0x00000008, ///  /// LVS_EX_HEADERDRAGDROP ///  HeaderDragDrop = 0x00000010, ///  /// LVS_EX_FULLROWSELECT ///  FullRowSelect = 0x00000020, ///  /// LVS_EX_ONECLICKACTIVATE ///  OneClickActivate = 0x00000040, ///  /// LVS_EX_TWOCLICKACTIVATE ///  TwoClickActivate = 0x00000080, ///  /// LVS_EX_FLATSB ///  FlatsB = 0x00000100, ///  /// LVS_EX_REGIONAL ///  Regional = 0x00000200, ///  /// LVS_EX_INFOTIP ///  InfoTip = 0x00000400, ///  /// LVS_EX_UNDERLINEHOT ///  UnderlineHot = 0x00000800, ///  /// LVS_EX_UNDERLINECOLD ///  UnderlineCold = 0x00001000, ///  /// LVS_EX_MULTIWORKAREAS ///  MultilWorkAreas = 0x00002000, ///  /// LVS_EX_LABELTIP ///  LabelTip = 0x00004000, ///  /// LVS_EX_BORDERSELECT ///  BorderSelect = 0x00008000, ///  /// LVS_EX_DOUBLEBUFFER ///  DoubleBuffer = 0x00010000, ///  /// LVS_EX_HIDELABELS ///  HideLabels = 0x00020000, ///  /// LVS_EX_SINGLEROW ///  SingleRow = 0x00040000, ///  /// LVS_EX_SNAPTOGRID ///  SnapToGrid = 0x00080000, ///  /// LVS_EX_SIMPLESELECT ///  SimpleSelect = 0x00100000 } public enum ListViewMessages { First = 0x1000, SetExtendedStyle = (First + 54), GetExtendedStyle = (First + 55), } ///  /// Contains helper methods to change extended styles on ListView, including enabling double buffering. /// Based on Giovanni Montrone's article on  ///  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); } } 

El ListView en CommonControls 6 (XP o más reciente) admite doble almacenamiento en búfer. Afortunadamente, .NET envuelve los CommonControls más nuevos en el sistema. Para habilitar el doble almacenamiento en búfer, envíe el mensaje de Windows apropiado al control ListView.

Aquí están los detalles: http://www.codeproject.com/KB/list/listviewxp.aspx

En .NET Winforms 2.0 existe una propiedad protegida llamada DoubleBuffered.

Al heredar de ListView, se puede configurar esta propiedad protegida como verdadera. Esto habilitará el doble buffer sin necesidad de llamar a SendMessage.

Establecer la propiedad DoubleBuffered es lo mismo que establecer el siguiente estilo:

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

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

Sé que esta pregunta es bastante antigua, pero como este es uno de los primeros resultados de búsqueda en Google, quería compartir mi solución.

La única forma en que podía eliminar el parpadeo al 100% era combinar la respuesta de Oliver (clase de extensión con doble almacenamiento en búfer) y utilizar los BeignUpdate() y EndUpdate() .

Ninguno de los dos por su cuenta podría arreglar el parpadeo para mí. De acuerdo, uso una lista muy compleja, que necesito ingresar a la lista y también necesito actualizarla casi cada segundo.

esto ayudará:

 class DoubleBufferedListView : System.Windows.Forms.ListView { public DoubleBufferedListView() :base() { this.DoubleBuffered = true; } } 

Si solo desea actualizar el texto, simplemente configure el texto del SubItem modificado directamente en lugar de actualizar todo ListViewItem (no ha dicho cómo está haciendo sus actualizaciones).

La anulación que muestra es equivalente a anular OnPaintBackground, que sería una forma administrada “más correcta” para realizar esa tarea, y no va a ser de ayuda para un solo elemento.

Si todavía tiene problemas, necesitaremos una aclaración sobre lo que realmente ha intentado.

Esta es una toma en la oscuridad, pero podrías intentar doble buffering el control.

 SetStyle( ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.DoubleBuffer, true) 

Llame al método BeginUpdate () en ListView antes de configurar cualquiera de los elementos de la vista de lista y solo llame a EndUpdate () después de que se hayan agregado todos los elementos.

Eso detendrá el parpadeo.

La solución simple es esto:

yourlistview.BeginUpdate ()

// Actualice agregar y eliminar elementos de la lista

yourlistview.EndUpdate ()