Pregunta

Tengo una vista de lista que estoy completando con 8 columnas de datos de usuario. El usuario tiene la opción de habilitar la actualización automática, lo que hace que ListView se borre y se vuelva a llenar con los últimos datos de la base de datos.

El problema es que cuando los elementos se borran y se vuelven a llenar, el área visible vuelve a la parte superior de la lista. Entonces, si estoy viendo el artículo 1000 de 2000, es muy inconveniente volver a ese artículo.

Básicamente, lo que pregunto es, ¿cómo obtengo las distancias de desplazamiento actuales (x e y) y luego las restauro?

¿Fue útil?

Solución

Tuve el mismo problema hace un tiempo y terminé implementando un algoritmo para comparar el modelo con la lista, así que solo agregué / eliminé elementos que habían cambiado. De esta manera, si no hubo cambios masivos, la lista no saltaría al principio. Y lo principal que quería lograr era la eficiencia (para que la lista no parpadeara).

Otros consejos

Solo quería proporcionar información para aquellos que intentan desesperadamente usar la propiedad BugView ListView.TopItem:

  1. DEBE establecer la propiedad TopItem DESPUÉS de llamar a ListView.EndUpdate
  2. Los elementos del control ListView DEBEN tener su propiedad Text establecida en algo diferente que String.Empty, o la propiedad no funcionará.
  3. Establecer ListView.TopItem arroja excepciones de referencia nulas de forma intermitente. Mantenga siempre esta línea de código dentro de un bloque Try ... Catch.

Por supuesto, esto hará que la barra de desplazamiento de ListView salte a 0 y regrese a la ubicación del elemento superior, lo cual es molesto. Actualice esta pregunta si encuentra una solución a este problema.

Utilicé lo siguiente con éxito:

int topItemIndex = 0;
try
{
     topItemIndex = listView1.TopItem.Index;
}
catch (Exception ex)
{ }
listView1.BeginUpdate();
listView1.Items.Clear();
//CODE TO FILL LISTVIEW GOES HERE
listView1.EndUpdate();
try 
{ 
    listView1.TopItem = listView1.Items[topItemIndex];
}
catch (Exception ex)
{ }

La propiedad TopItemIndex en ListView es lo que está buscando, sin embargo, tiene algunos errores confirmados que deberían haberse solucionado en la versión VS2010 ... no estoy seguro (no lo he verificado).

De todos modos, mi solución para hacer que esto funcione es hacer esto:

listViewOutput.TopItemIndex = outputList.Count - 1;
listViewOutput.TopItemIndex = myNewTopItemIndex;

Por alguna razón, configurarlo directamente no lo actualiza, pero configurarlo en el último elemento y luego el que quiero funciona de manera confiable para mí.

Mire la propiedad ListView.TopItem. Tiene un índice, que debe contener su posición en la lista. Busque ese índice en la nueva lista y establezca TopItem en ese elemento, y debería hacer el desplazamiento automáticamente.

Desafortunadamente, necesitará usar alguna interoperabilidad para desplazarse a la posición exacta en el ListView. Utilice la función winapi GetScrollInfo para obtener la posición de desplazamiento existente y SendMessage para desplazarse a la posición.

Allí en un artículo sobre CodeProject llamado Desplazarse a un grupo con un ListView que podría guiarte a la solución.

Mi solución para mantener la posición de desplazamiento:

Variable de nivel de formulario:

private static int scrollSpot = 0;

Actualización de vista de lista interior (es decir, Temporizador, botón) para almacenar el lugar actual:

scrollSpot = this.listView1.TopItem.Index;
refreshTheForm();

Dentro del método refreshTheForm para mostrar el lugar almacenado (puesto al final del método):

if (scrollSpot <= 1)
{
     listView1.Items[scrollSpot].Selected = true;
}
else
{
     listView1.Items[scrollSpot - 2].Selected = true;
}
listView1.TopItem = listView1.SelectedItems[0]; 

Estaba teniendo el mismo problema. Tengo un listView que relleno cada 1/2 segundo y cuando configuro el TopItem en un ListItem cuyo índice > elementos visibles, luego la lista saltó entre los elementos topItem y back 2.

Entonces, para corregir el problema, configuré el TopIterm DESPUÉS de la llamada a EndUpdate.

lvB.EndUpdate();
lvI.EndUpdate();
lvR.EndUpdate();

if (lstEntryInts.Items.Count > 0)
    lstEntryInts.TopItem = lstEntryInts.Items[iTopVisIdx];
if (lstEntryBools.Items.Count > 0)
    lstEntryBools.TopItem = lstEntryBools.Items[iTopVisIdx];
if (lstEntryReals.Items.Count > 0)
    lstEntryReals.TopItem = lstEntryReals.Items[iTopVisIdx];​

En mis pruebas, ni siquiera necesitaba el TopItem, aunque utilicé un int para guardar el elemento seleccionado. También TopItem lanza una excepción si está utilizando View.Tile o View.LargeIcon.

Este código no mueve las barras de desplazamiento:

listView1.BeginUpdate();
listView1.Items.Clear();

// loop through your add routine
listView1.Items.Add(lvi);

listView1.EndUpdate();
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top