【轉】【WPF】關於依賴屬性的ValidateValueCallback,PropertyChangedCallback和CoerceValueCallback的執行順序
阿新 • • 發佈:2017-10-16
value read ado args cep img 強制轉換 .cn clas
三個回調對應依賴屬性的驗證過程,改變過程和強制轉換過程。
class Dobj : DependencyObject { //依賴屬性包裝 public int MyProperty { get { return (int)GetValue(MyPropertyProperty); } set { SetValue(MyPropertyProperty, value); } } //註冊依賴屬性 //註意依賴屬性默認值是:71 public static readonly DependencyProperty MyPropertyProperty = DependencyProperty.Register("MyProperty", typeof(int), typeof(Dobj), new PropertyMetadata(71, PropertyChanged, CoerceValue), ValidateValue); //屬性改變 static void PropertyChanged(DependencyObject dobj, DependencyPropertyChangedEventArgs e) { Debug.WriteLine(String.Format("PropertyChanged - 屬性:{0} 新值:{1} 舊值:{2}", e.Property.Name, e.NewValue, e.OldValue)); }//強制轉換 static object CoerceValue(DependencyObject dobj, object newValue) { Debug.WriteLine(String.Format("CoerceValue - {0}", newValue)); return newValue; } //驗證 static bool ValidateValue(object obj) { Debug.WriteLine(String.Format("ValidateValue - {0}", obj));return true; } }
當僅僅定義一個新對象時:
var dobj = new Dobj();
調試下輸出:
ValidateValue - 71 ValidateValue - 71
驗證過程被執行了兩次,我不知道為什麽這樣。
接著修改這個對象的屬性。
var dobj = new Dobj(); dobj.MyProperty = 999;
輸出:
ValidateValue - 71 ValidateValue - 71 ValidateValue - 999 CoerceValue - 999 PropertyChanged - 屬性:MyProperty 新值:999 舊值:71
默認值被驗證了兩遍,接著驗證新值,強制轉換,最後屬性改變回調。
接下來修改一下驗證回調,把返回值改為false。
//驗證 static bool ValidateValue(object obj) { Debug.WriteLine(String.Format("ValidateValue - {0}", obj)); if ((int)obj == 999) return false; return true; }
賦值語句(SetValue方法)會拋出ArgumentException異常,消息:’999′ is not a valid value for property ‘MyProperty’.(999並不是MyProperty屬性的合法值)。
下面要做到內容是創建一個當前依賴對象的繼承類,並改寫父類依賴屬性的元數據。
代碼:
//繼承原來的依賴對象 class SuperDobj : Dobj { static SuperDobj() { //改寫父類依賴屬性的元數據,默認值改成81 Dobj.MyPropertyProperty.OverrideMetadata(typeof(SuperDobj), new PropertyMetadata(81, PropertyChanged, CoerceValue)); } //屬性改變 static void PropertyChanged(DependencyObject dobj, DependencyPropertyChangedEventArgs e) { Debug.WriteLine(String.Format("SuperDobj.PropertyChanged - 屬性:{0} 新值:{1} 舊值:{2}", e.Property.Name, e.NewValue, e.OldValue)); } //強制轉換 static object CoerceValue(DependencyObject dobj, object newValue) { Debug.WriteLine(String.Format("SuperDobj.CoerceValue - {0}", newValue)); if ((int)newValue == 999) throw new Exception("test"); return newValue; } }
還是像剛才,先定義一個對象:
var superdobj = new SuperDobj();
輸出:
ValidateValue - 71 ValidateValue - 71 ValidateValue – 81
父類和子類的驗證都要執行一遍。
接著設置子類的依賴屬性:
var superdobj = new SuperDobj(); superdobj.MyProperty = 999;
輸出:
ValidateValue - 71 ValidateValue - 71 ValidateValue - 81 ValidateValue - 999 SuperDobj.CoerceValue - 999 PropertyChanged - 屬性:MyProperty 新值:999 舊值:81 SuperDobj.PropertyChanged - 屬性:MyProperty 新值:999 舊值:81
這個結果很有意思。
看來子類和父類的驗證和屬性改變回調都會依次被調用,但是強制轉換只調用子類的。
事實上屬性元數據此時會調用PropertyMetadata.Merge方法來合並多個屬性元數據。可以參考MSDN:http://msdn.microsoft.com/zh-cn/library/system.windows.propertymetadata.merge.aspx
原文地址:https://www.mgenware.com/blog/?p=188
【轉】【WPF】關於依賴屬性的ValidateValueCallback,PropertyChangedCallback和CoerceValueCallback的執行順序