在 Visual Basic 中,随着 .NET 平台的发展,出现了扩展的集合,如 ObservableCollection(Of T)。该集合旨在通知用户界面(UI)数据的变化,这在数据绑定(data binding)时尤为重要——例如,在 WPF 或支持 MVVM 方法的 WinForms 中。早期的结构,如 List(Of T) 或 ArrayList,不支持自动变化通知,且需要手动重写显示逻辑。
普通集合不会通知界面或订阅对象自身的变化——添加、删除、重新排列元素。因此,UI 控件(例如列表、表格)不会自动更新,需要重绘或额外调用更新方法。此类手动同步会导致错误并使代码逻辑变得复杂。
ObservableCollection(Of T) 实现了 INotifyCollectionChanged 接口,这使得 UI 能够自动获取添加、删除或修改元素的任何信息。为了在集合中对对象本身的变化进行完整的数据更新,建议存储的元素同样实现 INotifyPropertyChanged 接口。
代码示例:
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($"动作: {e.Action}") End Sub items.Add(New Item() With {.Name = "测试 1"}) items(0).Name = "更新的名称"
关键特点:
INotifyPropertyChanged 以自动同步到 UI。如果元素被更改,但集合(组成、大小)没有变化,ObservableCollection 能否通知元素属性的变化?
不,ObservableCollection 默认只跟踪集合本身的变化,而不是单个元素的属性变化。要在 UI 中反映属性的变化,对象必须实现 INotifyPropertyChanged 接口,UI 中的绑定需要支持这一点。
如果集合在 UI 线程外进行修改,会发生变化通知吗?
不,集合在主(UI)线程外进行的更改将导致错误或在某些框架(例如 WPF)中出现不正确行为。对于多线程更改,必须使用 Dispatcher.Invoke 或类似方法,以确保同步在正确线程中进行。
ObservableCollection 可以用于 WinForms 绑定,还是只在 WPF 中工作?
ObservableCollection 在 WinForms 中也有效,但在 WinForms 中需要手动同步和更新数据,因为该平台的标准绑定并不总是能识别集合事件。在 WPF 中实现会更加透明。
ObservableCollection,但其中的元素未实现 INotifyPropertyChanged,因此在属性变化时 UI 并不会更新。程序员为界面创建商品列表,使用普通的 List(Of T),每次添加或删除元素后手动调用 UI 更新方法。有时忘记更新列表或在删除元素时错误地重新计算索引。
优点:
缺点:
引入了 ObservableCollection(Of T),并且对象支持 INotifyPropertyChanged。所有操作——添加、删除、修改——都通过绑定自动反映在界面上。UI 的逻辑简化为无需大量手动更新的响应。
优点:
缺点: