In Visual Basic, con lo sviluppo della piattaforma .NET, sono apparse collezioni avanzate come ObservableCollection(Of T). Questa collezione è progettata per notificare l'interfaccia utente (UI) sulle modifiche ai dati, il che è particolarmente importante quando si lavora con il binding dei dati (data binding) — ad esempio, in WPF o WinForms con supporto per l'approccio MVVM. Le strutture precedenti come List(Of T) o ArrayList non supportavano la notifica automatica delle modifiche e richiedevano una rielaborazione manuale della logica di visualizzazione.
Le collezioni comuni non avvisano l'interfaccia o gli oggetti sottoscritti delle proprie modifiche — aggiunta, rimozione, riordinamento degli elementi. Di conseguenza, i controlli UI (ad esempio, elenchi, tabelle) non si aggiornano automaticamente e richiedono un ridisegno o chiamate aggiuntive ai metodi di aggiornamento. Questa sincronizzazione manuale porta a errori e complica la logica del codice.
ObservableCollection(Of T) implementa l'interfaccia INotifyCollectionChanged, il che consente alla UI di apprendere automaticamente qualsiasi aggiunta, rimozione o modifica degli elementi. Per un aggiornamento completo dei dati durante la modifica degli oggetti stessi nella collezione, è consigliabile che gli elementi memorizzati implementino anche l'interfaccia INotifyPropertyChanged.
Esempio di codice:
Imports System.Collections.ObjectModel Imports System.ComponentModel Public Class Item Implements INotifyPropertyChanged Private _name As String Public Property Name As String Get Return _name End Get Set(value As String) If _name <> value Then _name = value RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Name")) End If End Set End Property Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged End Class Dim items As New ObservableCollection(Of Item)() AddHandler items.CollectionChanged, Sub(s, e) Console.WriteLine($"Azione: {e.Action}") End Sub items.Add(New Item() With {.Name = "Test 1"}) items(0).Name = "Nome Aggiornato"
Caratteristiche principali:
INotifyPropertyChanged per la sincronizzazione automatica con la UIPuò la ObservableCollection notificare le modifiche delle proprietà degli elementi se l'elemento viene modificato, ma la collezione stessa (composizione, dimensione) non cambia?
No, per impostazione predefinita ObservableCollection monitora solo le modifiche alla collezione stessa, non le proprietà di singoli elementi. Per riflettere le modifiche delle proprietà nella UI, gli oggetti devono implementare l'interfaccia INotifyPropertyChanged, e il binding nella UI deve supportarlo.
Si verificheranno notifiche di modifica se la collezione viene modificata al di fuori del thread UI?
No, le modifiche alla collezione al di fuori del thread principale (UI) porteranno a errori o comportamenti errati in alcuni framework (ad esempio, WPF). Per modifiche multithread è necessario utilizzare Dispatcher.Invoke o analoghi, affinché la sincronizzazione avvenga nel thread corretto.
Può essere utilizzata ObservableCollection per il binding in WinForms o funziona solo in WPF?
ObservableCollection funziona sia in WinForms, tuttavia in WinForms è necessaria una sincronizzazione manuale e un aggiornamento dei dati, poiché il binding standard di questa piattaforma non riconosce sempre gli eventi della collezione. In WPF l'implementazione è massimamente trasparente.
ObservableCollection, ma gli elementi al suo interno non implementano INotifyPropertyChanged, quindi la UI non si aggiorna quando cambiano le proprietàUn programmatore crea un elenco di prodotti per l'interfaccia, utilizza un comune List(Of T) e dopo ogni aggiunta o rimozione di elementi esegue manualmente chiamate ai metodi di aggiornamento della UI. A volte dimentica di aggiornare l'elenco o calcola erroneamente gli indici durante la rimozione di elementi.
Pro:
Contro:
È stata implementata ObservableCollection(Of T) e gli oggetti supportano INotifyPropertyChanged. Tutte le azioni — aggiunta, rimozione, modifica — si riflettono automaticamente nell'interfaccia grazie al binding. La logica della UI passa a una reazione semplificata, senza un gran numero di aggiornamenti manuali.
Pro:
Contro: