Datapayasadas

Julio 28, 2008

Evitando el parpadeo molesto en los ListView

Archivado en: C# — Etiquetas:, — Matías @ 10:06 am

Buenas,

No se si habrán notado que, por lo general, al actualizar frecuentemente un ListView (al menos en .Net Framework 2.0) se puede apreciar cierto parpadeo que puede llegar a resulta bastante molesto.
La situación rara vez se soluciona utilizando los métodos BeginUpdate() y EndUpdate(), incluso pueden empeorarla.

Investigando un poquito encontré en donde radica el problema: parece ser que la sobrecarga del método Update() del control está mal implementada, entonces actúa como si fuera un Refresh().

Un Update() debería hacer que el control redibuje solo la región invalidada, mientras que un Refresh() debería redibujar toda el área asignada al control, es decir, el control en su totalidad.

Por decirlo de algún modo, si queremos cambiar el color de fondo de un item en particular (propiedad BackColor), solo ese item debería ser redibujado. Desafortunadamente, esto no sucede … o mejor dicho, sucede pero no como debería; el ListView intenta redibujar toda la superficie a pesar de que solo hemos modificado un item.

Afortunadamente existe una forma de evitar esto, solo debemos hacer lo siguiente:

public class ListViewM : System.Windows.Forms.ListView
{
    public ListViewM()
    {
        // Activamos el DoubleBuffering
        // http://en.wikipedia.org/wiki/Double_buffering
        this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);

        // Activamos el evento OnNotifyMessage, asi tenemos la oportunidad
        // de filtrar los mensajes de Windows antes de que lleguen al WndProc
        // del formulario
        this.SetStyle(ControlStyles.EnableNotifyMessage, true);
    }

    protected override void OnNotifyMessage(Message m)
    {
        // Filtramos el mensaje WM_ERASEBKGND

        if (m.Msg != 0x14)
        {
            base.OnNotifyMessage(m);
        }
    }
}

Espero esta información les sea útil.

Hasta la próxima.

Fuentes:

http://geekswithblogs.net/cpound/archive/2006/02/27/70834.aspx

http://forums.msdn.microsoft.com/en-US/search/?q=ListView%20Flicker

Blog de WordPress.com.