ObservableCollection<T> 是 WPF 資料繫結的核心集合類別,位於 System.Collections.ObjectModel 命名空間,繼承自 Collection<T>,實作 INotifyCollectionChanged 與 INotifyPropertyChanged 介面。
CollectionChanged 事件,UI 自動更新。INotifyPropertyChanged,且消費者需自行訂閱各項目的 PropertyChanged 事件。NotifyCollectionChangedAction.Move。public class Customer : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string name) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
private string _name;
public string Name {
get => _name;
set { if (_name != value) { _name = value; OnPropertyChanged("Name"); } }
}
public Customer(string name) => _name = name;
}
public class CustomerList : ObservableCollection<Customer> {
private static readonly CustomerList _instance = new CustomerList();
public static CustomerList GetList() => _instance;
private CustomerList() { AddItems(); }
public static void Reset() {
_instance.Clear();
_instance.AddItems();
}
private void AddItems() {
Add(new Customer("Maria Anders"));
Add(new Customer("Ana Trujillo"));
Add(new Customer("Antonio Moreno"));
}
}
<ListBox DisplayMemberPath="Name"
ItemsSource="{Binding ElementName=MainWindow, Path=Data}" />
public partial class MainWindow : Window {
public CustomerList Data { get; } = CustomerList.GetList();
// ...
}
private void Data_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
if (e.Action == NotifyCollectionChangedAction.Add ||
e.Action == NotifyCollectionChangedAction.Remove) {
UpdateComboBox(); // 同步更新下拉選單索引
UpdateButtons();
}
}
NotifyCollectionChangedEventArgs 提供關鍵屬性:
| 屬性 | 說明 |
|---|---|
| Action | Add/Remove/Replace/Move/Reset |
| NewItems | 新加入的項目清單 |
| NewStartingIndex | 新項目起始索引 |
| OldItems | 被移除/取代/移動的舊項目 |
| OldStartingIndex | 舊項目起始索引 |
因集合不代理項目屬性變更,需自行掛接:
private void HookupChangeEventHandlers() {
foreach (var c in Data) HookupChangeEventHandler(c);
}
private void HookupChangeEventHandler(Customer c) {
c.PropertyChanged += HandlePropertyChanged;
}
// 新增/移除時同步掛接/移除事件
private void AddItem() {
var c = new Customer(txt.Text);
HookupChangeEventHandler(c);
Data.Add(c);
}
private void RemoveItem(int idx) {
if (idx >= 0) {
Data[idx].PropertyChanged -= HandlePropertyChanged;
Data.RemoveAt(idx);
}
}
private void HandlePropertyChanged(object sender, PropertyChangedEventArgs e) {
var cust = (Customer)sender;
var prop = typeof(Customer).GetProperty(e.PropertyName);
var newValue = prop.GetValue(cust, null);
MessageBox.Show($"屬性 '{e.PropertyName}' 已變更為 '{newValue}'");
}
注意:PropertyChangedEventArgs 僅提供屬性名稱,不含新舊值,需自行透過 Reflection 取得。
CollectionView 包裝集合,支援排序、篩選、分組等視圖操作,同一集合可建立多個不同視圖。ObservableCollection 的豐富繫結支援僅限 WPF;WinForms 需手動重新整理繫結,但至少可透過事件得知何時需更新。List<T> 或 Collection<T>,甚至非 WPF 專案,作為可觀測集合使用。