WPF 中依賴屬性的繼承(Inherits)


WPF中依賴屬性的值是是可以設置為可繼承(Inherits)的,這種模式下,父節點的依賴屬性會將其值傳遞給子節點。例如,數據綁定中經常使用的DataContextProperty:

    var host = new ContentControl();
    var button = new Button();
    host.Content = button;

    host.DataContext = Guid.NewGuid();
    Contract.Assert(object.Equals(host.DataContext, button.DataContext));

可以看到,雖然沒有顯示給button的DataContext賦值,但其自然沿襲的父節點的值。

這個特性很大程度上省去了我們的不少代碼,那么如何使用自定義的依賴屬性也具有這一特性呢,網上找到的例子一般如下:

    class Host : ContentControl
    {
        public object Value
        {
            get { return (object)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }

        public static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register("Value", typeof(object), typeof(Host), new FrameworkPropertyMetadata(null,
FrameworkPropertyMetadataOptions.Inherits));
    }

    class MyButton : Button
    {
        public object Value
        {
            get { return (object)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }

        public static readonly DependencyProperty ValueProperty =
Host.ValueProperty.AddOwner(typeof(MyButton), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits));

    }

可以看到,使能依賴屬性的基礎大體上要如下幾步:

  1. 使用 FrameworkPropertyMetadataOptions.Inherits使用 標記源屬性
  2. 使用 DependencyProperty.AddOwner注冊 衍生屬性,注冊時需要 FrameworkPropertyMetadataOptions.Inherits加上標記。

測試用例如下:

    var host = new Host();
    var button = new MyButton();

    host.Content = button;
    host.SetValue(Host.ValueProperty, Guid.NewGuid());
    Contract.Assert(object.Equals(host.GetValue(Host.ValueProperty), button.GetValue(MyButton.ValueProperty)));

這種方式雖然沒有什么問題,但Host.ValueProperty.AddOwner(typeof(MyButton)這一截看起來非常別扭,研究了一下,實際上沒有這么嚴格的父子關系,這樣寫也是可以的:

    class DependcyPropertyHelper
    {
        public static DependencyProperty RegistInherits<TOwner>(DependencyProperty property)
        {
            return property.AddOwner(typeof(TOwner), new FrameworkPropertyMetadata(property.DefaultMetadata.DefaultValue, FrameworkPropertyMetadataOptions.Inherits));
        }
    }

    class DependencyData : DependencyObject
    {
        public static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register("Value", typeof(object), typeof(DependencyData));
    }

    class Host : ContentControl
    {
        public static readonly DependencyProperty ValueProperty = DependcyPropertyHelper.RegistInherits<Host>(DependencyData.ValueProperty);
    }

    class MyButton : Button
    {
        public static readonly DependencyProperty ValueProperty = DependcyPropertyHelper.RegistInherits<MyButton>(DependencyData.ValueProperty);
    }

這樣寫看起來就舒服一些了。細心的朋友看下就能發現:源屬性DependencyData.ValueProperty沒有標記為可繼承的(第一種方式下非要標記為可繼承的),找了一下,也沒有發現官方的詳細文檔的說明這個規則到底是什么樣的,有空發現后再補充。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM