首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

進階基礎知識:ObservableCollection 類別深度解析

     編輯:關於.NET

ObservableCollection<T> 是 WPF 資料繫結的核心集合類別,位於 System.Collections.ObjectModel 命名空間,繼承自 Collection<T>,實作 INotifyCollectionChanged 與 INotifyPropertyChanged 介面。

核心特性

  • 集合變更通知:新增、移除、移動、取代、清除項目時引發 CollectionChanged 事件,UI 自動更新。
  • 屬性變更不自動通知:集合本身不監控項目內部屬性變更。若需感知項目屬性變更,項目類別必須實作 INotifyPropertyChanged,且消費者需自行訂閱各項目的 PropertyChanged 事件。
  • Move 方法:支援將項目移至新索引位置,觸發 NotifyCollectionChangedAction.Move。

範例架構

Customer 類別(實作 INotifyPropertyChanged)

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;
}

CustomerList(繼承 ObservableCollection,單例模式)

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"));
    }
}

WPF 視窗繫結

<ListBox DisplayMemberPath="Name"
         ItemsSource="{Binding ElementName=MainWindow, Path=Data}" />
public partial class MainWindow : Window {
    public CustomerList Data { get; } = CustomerList.GetList();
    // ...
}

事件處理實務

1. 處理 CollectionChanged 事件

private void Data_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
    if (e.Action == NotifyCollectionChangedAction.Add ||
        e.Action == NotifyCollectionChangedAction.Remove) {
        UpdateComboBox(); // 同步更新下拉選單索引
        UpdateButtons();
    }
}

NotifyCollectionChangedEventArgs 提供關鍵屬性:

屬性說明
ActionAdd/Remove/Replace/Move/Reset
NewItems新加入的項目清單
NewStartingIndex新項目起始索引
OldItems被移除/取代/移動的舊項目
OldStartingIndex舊項目起始索引

2. 手動訂閱項目 PropertyChanged

因集合不代理項目屬性變更,需自行掛接:

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);
    }
}

3. 取得變更後的屬性值(使用 Reflection)

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 取得。

重要觀念

  • WPF 內部會建立 CollectionView 包裝集合,支援排序、篩選、分組等視圖操作,同一集合可建立多個不同視圖。
  • ObservableCollection 的豐富繫結支援僅限 WPF;WinForms 需手動重新整理繫結,但至少可透過事件得知何時需更新。
  • 可替代任何 List<T> 或 Collection<T>,甚至非 WPF 專案,作為可觀測集合使用。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved