|
La ListView è un controllo complesso e di grande impatto visivo. È lo stesso tipo di lista usato dall'explorer di windows per visualizzare
files e cartelle. Le sue proprietà permettono di personalizzarne la visualizzazione in cinque stili diversi: i più importanti di questi
sono Large Icone (Icone grandi), Small Icon (Icone piccole) e Details (Dettagli). Ci sono poi anche Tile e List, ma vengono usati meno
spesso. Ecco alcuni esempi:

Large Icon

Small Icon

Details
ListView
Come al solito, ecco la compilation delle proprietà più interessanti:
- CheckBoxes : indica se la listview debba visualizzare delle CheckBox vicino ad ogni elemento
- Columns : collezione delle colonne disponibili. Ogni colonna è contraddistinta da un testo (Text), un indice d'immagine (ImageIndex) e
un indice di visualizzazione (DisplayIndex) che specifica la sua posizione ordinale nella visualizzazione. Le colonne sono visibili sono con
View = Details
- FullRowSelect : indica se evidenziare tutta la riga o solo il primo elemento, quando View = Details
- GridLines : indica su visualizzare le righe della griglia, quando View = Details
- Groups : collezione dei gruppi disponibili
- HeaderStyle : specifica se le intestazioni delle colonne possano essere cliccate o meno
- HideSelection : specifica se la listview debba nascondere la selezione quando perde il Focus, ossia quando un altro controllo diventa il
controllo attivo
- HotTracking : abilita gli elementi ad apparire come collegamenti ipertestuali quando il mouse ci passa sopra
- HoverSelection : se impostata su True, sarà possibile selezionare un elemento semplicemente sostandoci sopra con il mouse
- Items : collezione degli elementi della listview
- LabelEdit : specifica se sia possibile modificare il testo dei SubItems da parte dell'utente, quando View = Details
- LargeImageList : ImageList per View = Large Icon / Tile / List
- MultiSelect : indica se si possano selezionare più elementi contemporaneamente
- OwnerDraw : indica se gli elementi debbano essere disegnati dal controllo o dal codice del programmatore. Vedi articolo relativo
- ShowGroups : determina se visualizzare i gruppi
-
- ShowItemToolTips : determina se visualizzare i ToolTips dei rispettivi elementi
- SmallIconList : ImageList per View = Small Icon / Details
- Sorting : il tipo di ordinamento, se alfabetico ascendente o discendente.
ListViewItem
Ogni elemento della ListView è contraddistinto da un oggetto ListViewItem, che, a differenza di quanto avveniva cone le normali liste come
ListBox e ComboBox, non costituisce una semplice stringa (o un tipo base facilmente rappresentabile) ma un nucleo a sè stante, del quale
si possono personalizzare tutte le caratteristiche visive e stilistiche. Poichè la ListView è compatibile con
l'ImageList, tutti i membri della collezione Items sono in grado di impostare l'indice d'immagine associato, come si è analizzato nella lezione
scorsa. Inoltre, sempre manipolando le proprietà, si può attribuire ad ogni elemento un testo, un font, un colore diverso a seconda delle
necessità. Nella visualizzazione a dettagli si possono impostare tutti i valori corrispettivi ad ogni colonna mediante la proprietà SubItems,
la quale contiene una collezione di oggetti ListViewSubItem: di questi è possibile modificare il font e il colore, oltre che il testo.
ListViewGroup
Un gruppo è un insieme di elementi raggruppati sotto la stessa etichetta. I gruppi vengono aggiunti alla lista utilizzando l'apposita proprietà
Groups e ogni elemento può essere assegnato ad un gruppo con la stessa proprietà (ListViewItem.Group). Oggetti di questo tipo godono di
poche caratteristiche: solo il testo ed il nome sono modificabili. Prima di procedere con ogni operazione, però, bisogna assicurarsi che
la proprietà ShowGroups della ListView sia impostata a True, altrimenti... beh, niente festa.
Ecco un esempio di codice:
'Nuovo gruppo 'Testo esplicativo'
Dim G As New ListViewGroup("Testo esplicativo")
'Nuovo elemento 'Elemento'
Dim L As New ListViewItem("Elemento")
'Aggiunge il gruppo alla listview
ListView1.Groups.Add(G)
'Setta il gruppo a cui L apparterrà
L.Group = G
'Aggiunge l'elemento alla lista
ListView1.Items.Add(L)
ListView con View = Details
La ListView a dettagli è la versione più complessa di questo controllo, ed è contraddistinta dalla classica visualizzazione a colonne.
Ogni colonna viene determinata in fase di sviluppo o a run-time agendo sulla collezione Columns nelle proprietà della lista e bisogna
ricordare l'ordine in cui le colonne vengono inserite poichè questo influisce in maniera significativa sul comportamento dei SubItems. Infatti
il primo SubItem di un ListViewItem andrà sotto la prima colonna, quella con indice 0, il secondo sotto la seconda e così via. Un errore
di ordine potrebbe produrre quindi, risultati sgradevoli. Nell'esempio che segue, scriverò un breve programma per calcolare la spesa totale
conoscendo i singoli prodotti e le singole quantità di una lista della spesa. Ecco un'anteprima di come dovrebbe apparire la finestra:

I controlli usati sono deducibili dal nome e dall'utilizzo. Ecco quindi il codice:
Class Form1
Private Sub cmdAdd_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles cmdAdd.Click
'Nuovo elemento
Dim Item As ListViewItem
'Array dei valori che andranno a rappresentare i campi di
'ogni singola colonna
Dim Values() As String = _
{txtProduct.Text, nudPrice.Value, nudQuantity.Value}
'Inizializza Item sulla base dei valori dati
Item = New ListViewItem(Values)
'E lo aggiunge alla lista
lstProducts.Items.Add(Item)
End Sub
Private Sub cmdDelSelected_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles cmdDelSelected.Click
'Analizza tutti gli elementi selezionati
For Each SelItem As ListViewItem In lstProducts.SelectedItems
'E li rimuove dalla lista
lstProducts.Items.Remove(SelItem)
Next
End Sub
Private Sub cmdCalculate_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles cmdCalculate.Click
'Totale spesa
Dim Total As Single = 0
'Prezzo unitario
Dim Price As Single
'Quantit?
Dim Quantity As Int32
For Each Item As ListViewItem In lstProducts.Items
'Ottiene i valori da ogni elemento
Price = CSng(Item.SubItems(1).Text)
Quantity = CInt(Item.SubItems(2).Text)
Total += Price * Quantity
Next
MessageBox.Show("Totale della spesa: " & Total & ".", _
"Spesa", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
End Class
Per i più curiosi, mi addentrerò ancora un pò di più nel particolare, nella fattispecie su una caratteristica molto apprezzata in una
ListView a dettagli, ossia la possibilità di ordinare tutti gli elementi con un click. In questo caso, facendo click sull'intestazione
(header) di una colonna, sarebbe possibile ordinare gli elementi sulla base della qualità che quella colonna espone: per nome, per prezzo,
per quantità. Dato che il metodo Sort non accetta alcun overload che consenta di usare un Comparer, bisognerà implementare un algoritmo
che compari tutti gli elementi e li ordini. In questo esempio si fa ricorso a due classi che implementano l'interfaccia generica
IComparer(Of ListViewItem): il primo compara il nome del prodotto, mentre il secondo il prezzo e la quantità. Ecco il codice da aggiungere:
Class Form1
'Queste classi saranno i comparer usati per ordinare
'le righe della ListView, al pari di come si è imparato nelle
'lezioni sulle interfacce
Private Class ProductComparer
Implements IComparer(Of ListViewItem)
Public Function Compare(ByVal x As ListViewItem, _
ByVal y As ListViewItem) As Integer _
Implements IComparer(Of ListViewItem).Compare
'Gli oggetti da comparare sono ListViewItem, mentre la proprietà
'che bisogna confrontare è il nome del prodotto, ossia
'il primo sotto-elemento
Dim Name1 As String = x.SubItems(0).Text
Dim Name2 As String = y.SubItems(0).Text
Return Name1.CompareTo(Name2)
End Function
End Class
Private Class NumberComparer
Implements IComparer(Of ListViewItem)
Private Index As Int32
'Price è True se ci si riferisce al Prezzo (elemento 1)
'oppure False se ci si riferisce alla quantità (elemento 2)
Sub New(ByVal Price As Boolean)
If Price Then
Index = 1
Else
Index = 2
End If
End Sub
Public Function Compare(ByVal x As ListViewItem, _
ByVal y As ListViewItem) As Integer _
Implements IComparer(Of ListViewItem).Compare
'Qui bisogna ottenere il prezzo o la quantità: ci si basa
'sul parametro passato al costruttore
Dim Val1 As Single = x.SubItems(Index).Text
Dim Val2 As Single = y.SubItems(Index).Text
Return Val1.CompareTo(Val2)
End Function
End Class
'Scambia due elementi in una lista: dato che ListViewItem sono
'variabili reference, bisognerebbe clonarli per spostarne il valore,
'come si faceva con i valori value, in questo modo:
'Dim Temp As ListViewItem = L1.Clone()
'L1 = L2.Clone()
'L2 = Temp
'Ma si userebbe troppa memoria. Perciò la via più facile è
'usare i metodi della lista per scambiare gli elementi
Private Sub SwapInList(ByVal List As ListView, ByVal Index As Int32)
Dim Temp As ListViewItem = List.Items(Index + 1)
List.Items.RemoveAt(Index + 1)
List.Items.INSERT IGNORE(Index, Temp)
End Sub
'Ordina gli elementi con l'algoritmo Bubble Sort già
'descritto nell'ultima lezione teorica
Private Sub SortListViewItems(ByVal List As ListView, _
ByVal Comparer As IComparer(Of ListViewItem))
Dim Occurrences As Int32 = 0
Do
Occurrences = 0
For I As Int32 = 0 To List.Items.Count - 1
If I = List.Items.Count - 1 Then
Continue For
End If
If Comparer.Compare(List.Items(I), List.Items(I + 1)) = 1 Then
SwapInList(List, I)
Occurrences += 1
End If
Next
Loop Until Occurrences = 0
End Sub
Private Sub lstProducts_ColumnClick(ByVal sender As System.Object, _
ByVal e As ColumnClickEventArgs) Handles lstProducts.ColumnClick
Select Case e.Column
Case 0
'Nome
Me.SortListViewItems(lstProducts, New ProductComparer())
Case 1
'Prezzo
Me.SortListViewItems(lstProducts, New NumberComparer(True))
Case 2
'Quantità
Me.SortListViewItems(lstProducts, New NumberComparer(False))
End Select
End Sub
End Class |
|