elementos - listbox c# selecteditem
Invalidar solo un elemento en ListBox (2)
¿Hay alguna forma de invalidar un solo elemento en un ListBox
? Parece que no hay un método para obtener el rectángulo de un elemento, o incluso si un elemento específico es visible (aparte de llamar a IndexFromPoint
para cada píxel en el control / al menos cada píxel en una columna).
Esto es para C # WinForms (no para WPF).
Más información sobre lo que estoy tratando de hacer:
Tengo un ListBox
con muchos elementos, y quiero que aparezca un conjunto de "botones" en los elementos sobre los que pasas el cursor (como una X roja para eliminar). Lo estoy haciendo muy bien, excepto que en las listas con 10 o más elementos, cada vez que pasa el mouse sobre un nuevo elemento provoca un redibujado visible ya que invalido todo el control. Los datos no se cambian, solo se cambia la pantalla.
Editar: más información e intentos previos
Ya subclass ListBox
y realizar mi dibujo en OnDrawItem
por lo que se pueden utilizar los métodos protegidos de ListBox
.
He intentado lo siguiente con distintos niveles de éxito. La variable es el ListBox
extendido, el index
es el elemento sobre el que se dibujará, old_index
es el elemento sobre el que se dibujó anteriormente.
// Causes flicker of entire list, but works
this.Invalidate();
// Causes flicker of selected item, but works
int sel_index = this.SelectedIndex;
this.SelectedIndex = old_index;
this.SelectedIndex = index;
this.SelectedIndex = sel_index;
// Does not work
if (old_index >= 0)
this.RefreshItem(old_index);
if (index >= 0)
this.RefreshItem(index);
De acuerdo, estaba siendo tonto. Gracias a @LarsTech, decidí revisar la lista completa de las funciones de ListBox
nuevamente y encontré la apropiada: GetItemRectangle
e incluso es pública! No sé cómo me perdí esto durante la última hora ...
La solución de trabajo es:
if (old_index >= 0)
this.Invalidate(this.GetItemRectangle(old_index));
if (index >= 0)
this.Invalidate(this.GetItemRectangle(index));
Lo cual todavía produce un poco de parpadeo pero significativamente menos (solo visible cuando muevo el mouse sobre muchos muy rápidamente donde antes lo movía un solo elemento).
Sí, pero debe crear su propia versión del listbox heredándolo y exponiendo el método RefreshItem que Microsoft le oculta:
public class ListBoxEx : ListBox
{
public new void RefreshItem(int index)
{
base.RefreshItem(index);
}
}