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

WPF 依賴屬性通知機制完全攻略:從事件到集合監控

     編輯:關於.NET

依賴屬性基礎回顧

  • 定義 public static readonly DependencyProperty XxxProperty,DependencyProperty.Register 註冊。
  • CLR 屬性包裝 GetValue/SetValue。
  • 靜態回呼 PropertyChangedCallback 處理變更,建議轉呼叫實例方法。

繫結來源的三種通知機制 (互斥)

  1. 依賴屬性:來源與目標皆為 DP,優先採用。
  2. XXXChanged 事件:WinForms 風格 (如 EnabledChanged),WPF 不建議。
  3. INotifyPropertyChanged:實作 PropertyChanged 事件,適合非 DP 屬性。缺點:無法強制所有屬性觸發、無法靜態驗證。

自訂可通知集合:ObservableNotifiableCollection<T>

需求:集合中任一項目屬性變更時,觸發事件並告知「哪個項目、哪個屬性」。

  • 繼承 ObservableCollection<T> (已實作 INotifyCollectionChanged)。
  • 限制 T : INotifyPropertyChanged。
  • 重寫 OnCollectionChanged:新增項目訂閱 PropertyChanged,移除項目解除訂閱。
  • 項目觸發 PropertyChanged 時,集合轉發 ItemPropertyChanged 事件,參數含 Item 與 PropertyName。

依賴屬性缺乏公共事件的三種補救方案

1. 動態繫結技巧 (較奇特)

  • 在監控端動態註冊同型別 DP,建立 Binding 從目標物件來源繫結到自身新 DP。
  • 目標 DP 變更 → 觸發監控端 DP 回呼。
  • 缺點:監控多物件多屬性時,動態 DP 與 Binding 數量爆炸,難以管理。

2. Freezable 類別 (較強硬)

  • 繼承 Freezable,自動獲得 Changed 事件。
  • 任何巢狀子屬性 (含集合項目) 變更皆觸發 Changed,但 無法得知具體哪個屬性變更。
  • WPF 圖形系統大量使用 (Brush, Geometry, PathFigure 等),變更通知向上傳遞觸發整體重繪。
  • FreezableCollection<T> 同樣特性,T 需為 DependencyObject,若為 Freezable 則子屬性變更也觸發。

3. DependencyPropertyDescriptor (推薦、標準)

  • DependencyPropertyDescriptor.FromProperty(dp, ownerType) 取得描述元。
  • AddValueChanged(targetObj, handler) / RemoveValueChanged 訂閱特定物件特定 DP 變更。
  • 事件簽名為 EventHandler,sender 為目標物件,EventArgs 無資訊,需自行 GetValue 取得新值。

通用集合監控:ObservableDependencyObjectCollection<T>

整合 DependencyPropertyDescriptor 與 ObservableCollection<T>:

  • 限制 T : DependencyObject。
  • 建構函式可指定要監控的 DP 陣列,或自動反射取得型別及基類所有 public static DependencyProperty 欄位。
  • 內部 DescriptorWrapper 封裝每個 DP 的 Descriptor 與回呼。
  • OnCollectionChanged:項目加入/移除時批次 AddValueChanged/RemoveValueChanged。
  • 統一回呼 OnItemDependencyPropertyChanged 觸發 ItemDependencyPropertyChanged 事件,參數含 Item, Property, NewValue。

進階彈性設計建議

  • 依項目實際型別動態建立 DescriptorWrapper,避免重複。
  • 引用計數管理 DescriptorWrapper 生命週期,無項目使用時移除。
  • 可建立同時支援 DP、INotifyPropertyChanged、Freezable 的萬用集合。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved