doble - c#lista de lista parpadeante en la actualización
doble buffer c# (13)
Tengo una vista de lista que se actualiza periódicamente (cada 60 segundos). Me molestaba que tuviera un destello cada vez que salía. El método utilizado fue borrar todos los elementos y luego recrearlos. Decidí que, en lugar de borrar los artículos, simplemente escribiría directamente en la celda con el nuevo texto. ¿Es este un mejor enfoque o alguien tiene una mejor solución?
Además de las otras respuestas, muchos controles tienen un método [Begin|End]Update()
que puede usar para reducir el parpadeo al editar los contenidos, por ejemplo:
listView.BeginUpdate();
try {
// listView.Items... (lots of editing)
} finally {
listView.EndUpdate();
}
Aquí está mi solución rápida para una implementación de C # que no requiere subclases de las vistas de lista, etc.
Utiliza la reflexión para configurar la propiedad DoubleBuffered para probar en el constructor de formularios.
lvMessages
.GetType()
.GetProperty("DoubleBuffered", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)
.SetValue(lvMessages, true, null);
El control ListView tiene un problema de parpadeo. El problema parece ser que la sobrecarga de actualización del control está implementada incorrectamente de modo que actúa como una actualización. Una actualización debe hacer que el control vuelva a dibujar solo las regiones no válidas, mientras que una actualización vuelve a dibujar el área de cliente completa del control. Entonces, si tuviera que cambiar, por ejemplo, el color de fondo de un elemento en la lista, entonces solo ese elemento en particular debería ser repintado. Desafortunadamente, el control ListView parece ser de una opinión diferente y quiere volver a pintar toda su superficie cada vez que se mete con un solo elemento ... incluso si el elemento no se muestra actualmente. Por lo tanto, de todos modos, puede suprimir fácilmente el parpadeo haciendo rodar el suyo de la siguiente manera:
class ListViewNF : System.Windows.Forms.ListView
{
public ListViewNF()
{
//Activate double buffering
this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
//Enable the OnNotifyMessage event so we get a chance to filter out
// Windows messages before they get to the form''s WndProc
this.SetStyle(ControlStyles.EnableNotifyMessage, true);
}
protected override void OnNotifyMessage(Message m)
{
//Filter out the WM_ERASEBKGND message
if(m.Msg != 0x14)
{
base.OnNotifyMessage(m);
}
}
}
En Winrt Windows phone 8.1 puede establecer el siguiente código para solucionar este problema.
<ListView.ItemContainerTransitions>
<TransitionCollection/>
</ListView.ItemContainerTransitions>
Excelente pregunta y la respuesta de Stormenent fue acertada. Aquí hay un puerto C ++ de su código para cualquier otra persona que pueda estar abordando implementaciones de C ++ / CLI.
#pragma once
#include "Windows.h" // For WM_ERASEBKGND
using namespace System;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
public ref class FlickerFreeListView : public ListView
{
public:
FlickerFreeListView()
{
//Activate double buffering
SetStyle(ControlStyles::OptimizedDoubleBuffer | ControlStyles::AllPaintingInWmPaint, true);
//Enable the OnNotifyMessage event so we get a chance to filter out
// Windows messages before they get to the form''s WndProc
SetStyle(ControlStyles::EnableNotifyMessage, true);
}
protected:
virtual void OnNotifyMessage(Message m) override
{
//Filter out the WM_ERASEBKGND message
if(m.Msg != WM_ERASEBKGND)
{
ListView::OnNotifyMessage(m);
}
}
};
Intente configurar la propiedad de doble búfer en verdadero.
También podrías usar:
this.SuspendLayout();
//update control
this.ResumeLayout(False);
this.PerformLayout();
La solución más simple probablemente sería usar
listView.Items.AddRange(listViewItems.ToArray());
en lugar de
foreach (ListViewItem listViewItem in listViewItems)
{
listView.Items.Add(listViewItem);
}
Esto funciona mucho mejor.
Por lo que vale, en mi caso, simplemente tuve que agregar una llamada a
Application.EnableVisualStyles ()
antes de ejecutar la aplicación, así:
private static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}
De lo contrario, el doble buffer no es suficiente. Tal vez fue un proyecto muy antiguo y los nuevos tienen esa configuración por defecto ...
Puede usar la siguiente clase de extensión para establecer la propiedad DoubleBuffered
en true
:
using System.Reflection;
public static class ListViewExtensions
{
public static void SetDoubleBuffered(this ListView listView, bool value)
{
listView.GetType()
.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic)
.SetValue(listView, value);
}
}
Sé que esta es una pregunta y respuesta muy antigua. Sin embargo, este es el resultado principal al buscar "C ++ / cli listview flicker", a pesar de que ni siquiera se trata de C ++. Así que aquí está la versión C ++ de esto:
Puse esto en el archivo de encabezado para mi formulario principal, puede elegir ponerlo en otro lugar ...
static void DoubleBuffer(Control^ control, bool enable) {
System::Reflection::PropertyInfo^ info = control->GetType()->
GetProperty("DoubleBuffered", System::Reflection::BindingFlags::Instance
| System::Reflection::BindingFlags::NonPublic);
info->SetValue(control, enable, nullptr);
}
Si aterriza aquí buscando una respuesta similar para C ++ administrado, eso funciona para mí. :)
Sí, haz doble buffer. Reducirá el parpadeo;) http://msdn.microsoft.com/en-us/library/system.windows.forms.listview.doublebuffered.aspx
Si esto puede ayudar, el siguiente componente solucionó mis problemas de parpadeo de ListView con .NET 3.5
[ToolboxItem(true)]
[ToolboxBitmap(typeof(ListView))]
public class ListViewDoubleBuffered : ListView
{
public ListViewDoubleBuffered()
{
this.DoubleBuffered = true;
}
}
Lo uso en conjunción con los métodos .BeginUpdate () y .EndUpdate () donde hago la manipulación de ListView.Items.
No entiendo por qué esta propiedad está protegida ... incluso en .NET 4.5 (tal vez un problema de seguridad)
Solución simple
yourlistview.BeginUpdate()
//Do your update of adding and removing item from the list
yourlistview.EndUpdate()