Domanda

Ho una visualizzazione elenco che sto popolando con 8 colonne di dati utente. L'utente ha la possibilità di abilitare l'aggiornamento automatico, il che fa sì che ListView venga cancellato e ripopolato con gli ultimi dati dal database.

Il problema è che quando gli elementi vengono cancellati e ripopolati, l'area visibile torna in cima all'elenco. Quindi, se sto guardando l'articolo 1000 del 2000, è molto scomodo tornare a quell'articolo.

Fondamentalmente, quello che sto chiedendo è, come posso ottenere le distanze di scorrimento correnti (xey) e quindi ripristinarle?

È stato utile?

Soluzione

Ho avuto lo stesso problema con un po 'di tempo fa e ho finito per implementare un algoritmo per confrontare il modello con l'elenco, quindi ho aggiunto / rimosso solo elementi che erano cambiati. In questo modo, se non ci fossero cambiamenti di massa, l'elenco non saltava all'inizio. E la cosa principale che volevo ottenere era l'efficienza (in modo che l'elenco non lampeggi).

Altri suggerimenti

Volevo solo fornire alcune informazioni a coloro che cercano disperatamente di utilizzare la proprietà ListView.TopItem con errori:

  1. DEVI impostare la proprietà TopItem DOPO aver chiamato ListView.EndUpdate
  2. Gli elementi del controllo ListView DEVONO avere la proprietà Text impostata su qualcos'altro di String.Empty o la proprietà non funzionerà.
  3. L'impostazione di ListView.TopItem genera eccezioni di riferimento null in modo intermittente. Conserva sempre questa riga di codice all'interno di un blocco Try ... Catch.

Naturalmente, ciò farà sì che la barra di scorrimento di ListView salti a 0 e torni alla posizione dell'elemento in alto, il che è fastidioso. Aggiorna questa domanda se trovi una soluzione alternativa a questo problema.

Ho usato con successo quanto segue:

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 proprietà TopItemIndex su ListView è ciò che stai cercando, tuttavia ha alcuni bug confermati che avrebbero dovuto essere risolti nella versione VS2010 .. non sono sicuro (non hanno controllato).

Ad ogni modo, la mia soluzione alternativa per fare questo lavoro è di fare questo:

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

Per qualche motivo, impostarlo direttamente non lo aggiorna, ma impostarlo sull'ultimo elemento e quindi quello che voglio funziona in modo affidabile per me.

Guarda la proprietà ListView.TopItem. Ha un indice, che dovrebbe contenere la sua posizione nell'elenco. Trova quell'indice nel nuovo elenco e imposta TopItem su quell'elemento e dovrebbe scorrere automaticamente.

Sfortunatamente dovrai usare l'interoperabilità per scorrere fino alla posizione esatta in ListView. Utilizzare GetScrollInfo winapi per ottenere la posizione di scorrimento esistente e SendMessage per scorrere fino alla posizione.

Lì in un articolo su CodeProject chiamato Scorrimento fino a un gruppo con un ListView che potrebbe guidarti alla soluzione.

La mia soluzione per mantenere la posizione di scorrimento:

Variabile a livello di modulo:

private static int scrollSpot = 0;

Aggiornamento elenco interno (ad es. timer, pulsante) per memorizzare lo spot corrente:

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

Metodo refreshTheForm interno per mostrare lo spot memorizzato (messo alla fine del metodo):

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

Stavo avendo lo stesso problema. Ho un listView che popolo ogni 1/2 sec e quando imposto TopItem su un ListItem il cui indice > oggetti visibili, quindi l'elenco è saltato tra i punti topItem e back 2.

Quindi, per correggere il problema, ho impostato il TopIterm DOPO la chiamata 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];​

Nei miei test, non hai nemmeno bisogno di TopItem, anche se ho usato un int per salvare l'elemento selezionato. Anche TopItem genera un'eccezione se si utilizza View.Tile o View.LargeIcon.

Questo codice non sposta le barre di scorrimento:

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

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

listView1.EndUpdate();
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top