(4) C# 依賴項屬性


  把對象賦值給屬性

 一、依賴屬性

1.定義依賴屬性

一般情況下只是使用,但如果要自定義WPF控件或者給現有的WPF控件增加新功能時就需要自定義。

定義時需要用到特殊的語法:

  • 靜態的
  • 使用readonly只能在構造時初始化
  • 必須是DependencyProperty類實例
  • 屬性名稱后面要帶上Property

定義一個Margin依賴項屬性的例子

public static readonly DependencyProperty MarginProperty;

 

2.注冊依賴屬性

(1)創建FrameworkPropertyMetadata對象,指明通過依賴項屬性使用什么服務(支持數據綁定,動畫,日志等)

FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata(new Thickness(), FrameworkPropertyMetadataOptions.AffectsMeasure);

 

(2)調用DependencyProperty.Register()靜態方法注冊屬性 

五個參數

  • 屬性名
  • 屬性使用的數據類型
  • 擁有該屬性的類型
  • 具有附加屬性設置的FrameworkPropertyMetadata對象(此參數可選)
  • 用於驗證屬性的回調函數(此參數可選)

在構造函數中

MarginProperty = DependencyProperty.Register("Margin", typeof(Thickness), typeof(FrameworkElement), metadata, new ValidateValueCallback(FrameworkElement.IsMarginValid));

 

3.封裝WPF依賴屬性

使用DependencyObject類的SetValue()和GetValue()方法

        public Thickness Margin
        {
            set { SetValue(MarginProperty, value); }
            get { return (Thickness)GetValue(MarginProperty); }
        }

設置屬性

element.Margin = new Thickness(5);

 

4.例子

一個按鈕繼承關系 Button--》ButtonBase--》ContentControl--》Control--》FrameworkElement--》UIElement--》Visual--》DependencyObject--》DispatcherObject--》Object

其中

  • ButtonBase 表示所有 Button 控件的基類,在System.Windows.Controls.Primitives命名空間下(和winfrom下的ButtonBase雖然名字相同,但完全是兩條不同的路線)
  • ContentControl  表示包含一段任意類型內容的控件
  • Control 表示用戶界面 (UI) 元素的基類,這些元素使用 ControlTemplate 來定義其外觀
  • FrameworkElement 提供 WPF元素的屬性、事件和方法的 WPF 框架級別集
  • UIElement 是 WPF 核心級實現的基類,這些實現是在 WPF元素和基本表示特性上生成的
  • Visual 為 WPF 中的呈現提供支持,其中包括命中測試、坐標轉換和邊界框計算
  • DependencyObject 表示參與依賴屬性系統的對象,如果設置依賴屬性直接繼承此類即可

 

完整代碼:自定義FrameworkElement類

    class FrameworkElement:UIElement
    {
        public static readonly DependencyProperty MarginProperty;
        
        static FrameworkElement()
        {
            FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata(new Thickness(), FrameworkPropertyMetadataOptions.AffectsMeasure);
            MarginProperty = DependencyProperty.Register("Margin", typeof(Thickness), typeof(FrameworkElement), metadata, new ValidateValueCallback(FrameworkElement.IsMarginValid));
        }

        private static bool IsMarginValid(object value)
        {
            throw new NotImplementedException();
        }

        public Thickness Margin
        {
            set { SetValue(MarginProperty, value); }
            get { return (Thickness)GetValue(MarginProperty); }
        }
    }

去掉ValidateValueCallback參數

使用

            FrameworkElement element = new FrameworkElement();
            element.Margin = new Thickness(5);

 

4.依賴屬性變更通知

有兩種方式通知依賴屬性變化 --后補

(1)屬性值創建綁定

(2)編寫能夠自動改變其他屬性或開始動畫的觸發器

 

5.共享依賴屬性

查看TextBlock源碼,沒有用DependencyProperty.Register注冊,而是使用了TextElement的FontFamilyProperty的依賴屬性

FontFamilyProperty = TextElement.FontFamilyProperty.AddOwner(typeof(TextBlock));

 

6.附加依賴屬性

附加屬性被應用的類不是定義附加屬性的那個類,

比如  DockPanel 的DockProperty屬性

[CommonDependencyProperty]
public static readonly DependencyProperty DockProperty;
      
static DockPanel()
{
  DockProperty = DependencyProperty.RegisterAttached("Dock", typeof(Dock), typeof(DockPanel), new FrameworkPropertyMetadata(Dock.Left, OnDockChanged), IsValidDock);       
}

DockPanel.Dock 屬性作用到了Border上

    <DockPanel LastChildFill="True">
        <Border Height="25" Background="SkyBlue" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Top">
            <TextBlock Foreground="Black">Dock = "Top"</TextBlock>
        </Border>
        <Border Height="25" Background="SkyBlue" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Top">
            <TextBlock Foreground="Black">Dock = "Top"</TextBlock>
        </Border>
        <Border Height="25" Background="LemonChiffon" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Bottom">
            <TextBlock Foreground="Black">Dock = "Bottom"</TextBlock>
        </Border>
        <Border Width="200" Background="PaleGreen" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Left">
            <TextBlock Foreground="Black">Dock = "Left"</TextBlock>
        </Border>
        <Border Background="White" BorderBrush="Black" BorderThickness="1">
            <TextBlock Foreground="Black">This content will "Fill" the remaining space</TextBlock>
        </Border>
    </DockPanel>

 

 附加屬性不需要進行屬性封裝,可以用於任何依賴對象

 

 

二、屬性驗證

1.驗證回調

 

2.強制回調

 


免責聲明!

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



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