W Visual Basic, wraz z rozwojem platformy .NET, pojawiły się rozszerzone kolekcje, takie jak ObservableCollection(Of T). Ta kolekcja jest przeznaczona do powiadamiania interfejsu użytkownika (UI) o zmianach danych, co jest szczególnie ważne przy pracy z danymi związanymi (data binding) — na przykład w WPF lub WinForms z obsługą podejścia MVVM. Wczesne konstrukcje takie jak List(Of T) lub ArrayList nie wspierały automatycznego powiadamiania o zmianach i wymagały ręcznego przetwarzania logiki wyświetlania.
Zwykłe kolekcje nie powiadamiają interfejsu ani obiektów subskrybujących o swoich własnych zmianach — dodaniu, usunięciu, przestawieniu elementów. W rezultacie kontrolki UI (np. listy, tabele) nie są automatycznie aktualizowane i wymagają ponownego rysowania lub dodatkowych wywołań metod aktualizacji. Taka ręczna synchronizacja prowadzi do błędów i komplikacji logiki kodu.
ObservableCollection(Of T) implementuje interfejs INotifyCollectionChanged, co pozwala UI automatycznie dowiadywać się o każdym dodaniu, usunięciu lub zmianie elementów. Dla pełnej aktualizacji danych przy zmianie samych obiektów w kolekcji zaleca się, aby przechowywane elementy również implementowały interfejs INotifyPropertyChanged.
Przykład kodu:
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($"Akcja: {e.Action}") End Sub items.Add(New Item() With {.Name = "Test 1"}) items(0).Name = "Zaktualizowana nazwa"
Kluczowe cechy:
INotifyPropertyChanged dla automatycznej synchronizacji z UICzy ObservableCollection może powiadamiać o zmianie właściwości elementów, jeśli element jest zmieniany, ale sama kolekcja (skład, rozmiar) się nie zmienia?
Nie, domyślnie ObservableCollection śledzi tylko zmiany samej kolekcji, a nie właściwości poszczególnych elementów. Aby odzwierciedlić zmiany właściwości w UI, obiekty muszą implementować interfejs INotifyPropertyChanged, a wiązanie w UI musi to wspierać.
Czy będą miały miejsce powiadomienia o zmianach, jeśli kolekcja jest modyfikowana poza wątkiem UI?
Nie, zmiany w kolekcji poza głównym (UI) wątkiem doprowadzą do błędów lub nieprawidłowego zachowania w niektórych frameworkach (np. WPF). Dla zmian wielowątkowych należy zastosować Dispatcher.Invoke lub analogi, aby synchronizacja odbywała się w odpowiednim wątku.
Czy można używać ObservableCollection do wiązania w WinForms, czy działa tylko w WPF?
ObservableCollection działa również w WinForms, jednak w WinForms wymagana jest ręczna synchronizacja i aktualizacja danych, ponieważ standardowe wiązanie tej platformy nie zawsze rozpoznaje zdarzenia kolekcji. W WPF implementacja jest maksymalnie przezroczysta.
ObservableCollection, ale elementy w niej nie implementują INotifyPropertyChanged, przez co UI nie jest aktualizowane przy zmianie właściwościProgramista tworzy listę produktów dla interfejsu, używa zwykłego List(Of T), i po każdym dodaniu lub usunięciu elementów ręcznie wykonuje wywołania metod aktualizacji UI. Czasami zapomina o aktualizacji listy lub błędnie oblicza indeksy przy usuwaniu elementów.
Zalety:
Wady:
Wprowadzono ObservableCollection(Of T) i obiekty wspierają INotifyPropertyChanged. Wszystkie działania — dodanie, usunięcie, zmiana — automatycznie odzwierciedlają się w interfejsie dzięki wiązaniu. Logika UI przechodzi na uproszczoną reakcję, bez licznych ręcznych aktualizacji.
Zalety:
Wady: