1. 程式人生 > >【轉】【WPF】關於依賴屬性的ValidateValueCallback,PropertyChangedCallback和CoerceValueCallback的執行順序

【轉】【WPF】關於依賴屬性的ValidateValueCallback,PropertyChangedCallback和CoerceValueCallback的執行順序

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的執行順序