Selezionare Item Listview

martedì 03 aprile 2007 - 00.29

breton79 Profilo | Newbie

Ciao a tutti, ho un problema con le listview.
Avrei bisogno di mantenere attiva la selezione di un Item, anche dopo un
refresh della listview.
Attualmente la mia applicazione ogni 15 sec. ricarica la listview da DB e
puntualmente la selezione dell'Item scompare.
Io vorrei, prima di aggiornare la listview, recuperare l'ultimo Item
selezionato e, dopo l'aggiornamento della listview, rimpostare la selezione
dell'Item memorizzato .
Come posso risolvere questo problema?

Grazie

munissor Profilo | Senior Member

Se hai il modo di distinguere gli item uno dall'altro in base ad un "codice" per esempio dovresti fare:

Salvare il codice dell'item selezionato
Ricaricare la lista
Scorrere la lista e impostare l'item corrispondente al codice che hai salvato come selezionato.

Salvare il ListViewItem non ha senso in quanto gli elementi cambiano...

Ciao

breton79 Profilo | Newbie

Sono riuscito a risolvere il problema, vi scrivo come:
Prima di ripopolare la listview eseguo la memorizzazione del Tag riferito all'Item selezionato e all'indice dello stesso Item in questo modo
try
{
itemtag = lstfile.FocusedItem.Tag.ToString();
itemid = lstfile.FocusedItem.Index;
}
catch
{
itemid = -1;
itemtag = "";
}

// Popolo la listview
....
....

Verifico se la variabile "itemtag" non è vuota e quindi posso selezionare l'Item
if (itemtag != "")
{
try
{
lstfile.Items[itemid].Focused = true;
lstfile.Items[itemid].Selected = true;
}
catch
{
// non faccio nulla
}
}

Facendo in questo modo, sembra che tutto funzioni correttamente.
Ho riportato il codice in modo da poter verificare insieme a voi se ciò che ho scritto è corretto o meno, visto che sono alle prime armi.
Ciao a tutti e grazie

munissor Profilo | Senior Member

Visto che sei alle prime armi ti correggo due cosette

try
{
//itemtag = lstfile.FocusedItem.Tag.ToString();
itemtag = (string)lstfile.FocusedItem.Tag; // se ti aspetti una stringa questo è molto meglio!
itemid = lstfile.FocusedItem.Index;
}
catch // usa il meno possibile catch senza filtro. se devi intercettare tutte le eccezioni usa catch(Exception) o meglio intercetta solo l'eccezione specifica per il codice che stai proteggendo...
{
itemid = -1;
itemtag = "";
}

// Popolo la listview
....
....

Verifico se la variabile "itemtag" non è vuota e quindi posso selezionare l'Item
if (itemtag != "")
{
try
{
lstfile.Items[itemid].Focused = true;
lstfile.Items[itemid].Selected = true;
}
catch
{
// non faccio nulla
}
}


PS: poi ho alcuni dubbi su cosa succede se un elemento che sta prima dell'elemento selezionato viene eliminato.. se memorizzi l'indice dovrebbe attivarti un elemento sbagliato...

breton79 Profilo | Newbie

Ti ringrazio per avermi risposto.
Effettivamente hai ragione, se elimino un Item che precede quello selezionato, la selezione che viene effettuata è sbagliata. Ho pensato di modificare il codice in questo modo:

// dopo aver verificato che il tag non sia nullo
if (itemtag != "")
{
try
{
foreach (ListViewItem item in lstfile.Items)
{
if (itemtag == item.Tag.ToString())
{
item.Focused = true;
item.Selected = true;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}

In questo modo controllo il valore del Tag invece che l'Index dell'Item evitando il precedente problema.

Volevo chiederti come mai è preferibile scrivere
itemtag = (string)lstfile.FocusedItem.Tag;
invece che
itemtag = lstfile.FocusedItem.Tag.ToString();
e se è una formula sempre conveniente.
Grazie

munissor Profilo | Senior Member



bhe..il motivo è semplice, cercherò di spiegare in modo semplice usando come esempio proprio il ListViewItem...

Supponiamo che tu inizializzi Tag con un campo di un altro oggetto..

item.Tag = mioOggetto.Name; // Name è di tipo string..

Tu sai per certo che Tag può essere o una string, o riferimento null..

il primo motivo per usare il cast è che item.Tag.ToString() quando Tag è null genera eccezione. E' sempre meglio evitare di generare eccezioni "inutili" come in questo caso. Il codice (string)item.Item ti restituisce sempre una stringa o null..

il secondo motivo è prevenire errori nascosti. Tag è di tipo Object, quindi può contenere oggetti di qualsiasi tipo. Se per una distrazione sbagli e scrivi codice del genere

item.Tag = mioOggetto; // Name è stato volutamente omesso..simuliamo errore..

(string)item.Tag ti genera InvalidCastException la prima volta che esegui il codice.. quindi avendo il codice fresco in testa è molto facile scovare l'errore...
item.Tag.ToString() invece ti restituisce comunque una stringa (che nel caso di default è il nome completo del tipo es: "MioNamespace.MioTipo" ) che, prendendo sempre come esempio il tuo caso, è sempre identico per tutti gli elementi.. andando poi a selezionare i ListViewItem dopo il ricaricamento ti selezionerebbe sempre il primo elemento e (credimi) la cosa non è immediata da scovare


In genere io uso questa regole:

1) se posso usare oggetti tipizzati in fase di compilazione lo faccio..è sempre la scelta migliore.
1) se devo usare oggetti non tipizzati uso cast se mi aspetto che l'oggetto sia sempre dello stesso tipo (o cmq derivante dallo stesso tipo), altrimenti si usano metodi di conversioni più sicuri di .ToString() quali Convert, tipo.Parse o TryParse, TypeConverter, ecc...

Spero di essere stato chiaro..in caso contrario sono sempre disponbile.

Ciao!


breton79 Profilo | Newbie

Sei stato molto chiaro, ti ringrazio molto.
A presto.
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5