WPF=Code+Markup 筆記 8

bjq_ren發表於2008-08-11

8 依賴屬性

 

依賴屬性,Dependency Property

在使用上只需注意兩點:

在一棵XAML視覺樹上

       1.當一個物件被明確設定依賴屬性時,它的子孫都得到同樣的屬性

       2.如果某個物件被明確設定屬性,它就不再沿襲父親的這個屬性。此後,再改變父親的屬性,這個物件也不再受影響。

 

 

Control類的FontSize屬性的思考:

    public class Control : FrameworkElement

    {

        double fontSize = 11;

 

        public double FontSize

        {

            get

            {

                return fontSize;

            }

            set

            {

                fontSize = value;

                ……

            }

        }

    }

 

set寫屬性時,省略一些程式碼,用來激發其他事件。這裡需要一種機制,以真正省略這些程式碼——這就是依賴屬性的用意。

 

為此建立public而且static的只讀欄位FontSizeProperty,從而這個欄位是和類相關而不是關聯到物件,而且它只能在靜態建構函式中被設定。

 

    public partial class Control : FrameworkElement

    {

        public static readonly DependencyProperty FontSizeProperty;

 

        static Control()

        {

            FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata();

            metadata.DefaultValue = 11;

            metadata.AffectsMeasure = true;

            metadata.Inherits = true;

            metadata.IsDataBindingAllowed = true;

            metadata.DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;

 

            FontSizeProperty = DependencyProperty.Register("FontSize", typeof(double), typeof(Control), metadata, ValidateFontSize);

        }

 

        static bool ValidateFontSize(Object obj)

        {

            double dFontSize = (double)obj;

            return dFontSize > 0 && dFontSize < 35791;

        }

    }

 

注意這個物件的建立,使用了DependencyProperty.Register靜態方法。

過載方法1

            FontSizeProperty = DependencyProperty.Register("FontSize", typeof(double), typeof(Control));

三個引數分別為“和此依賴屬性關聯的名稱字串”、“屬性的資料型別”、“註冊此屬性的類別”。

過載方法2

            FontSizeProperty = DependencyProperty.Register("FontSize", typeof(double), typeof(Control), metadata, ValidateFontSize);

多了兩個引數,討論如下

有時候還需要metadata,來描述這個屬性的重要資訊。其中DefaultValue用來取代私有欄位fontSizeAffectsMeasure一般設定為true,會使得FontSizeset屬性設定時,以新的FontSize進行重繪;Inherits則影響這個控制元件以下的所有子孫,在FontSizeset屬性設定時,將這個新的FontSize值向下傳。

ValidateFontSize這個callback方法,則用於FontSizeset屬性設定時呼叫,以決定這個值是否合適。不合適也就是返回方法返回false,就丟擲一個異常。

 

此時,改寫FontSize屬性,使其不再依賴私有欄位fontSize,而是依賴於FontSizeProperty欄位,並通過GetValeSetValue這兩個派生於DependencyObject的方法來操作,裡面省略了一些內部處理的程式碼,包括很多事件的觸發,如設定屬性時對窗體重繪和子孫的影響。

    public partial class Control : FrameworkElement

    {

        public double FontSize

        {

            get

            {

                return (double)GetValue(FontSizeProperty);

            }

            set

            {

                SetValue(FontSizeProperty, value);

            }

        }

    }

 

 

自定義一個依賴屬性

仿照對Control類的研究,設計一個帶有依賴屬性SpacePropertySpaceButton

    public class SpaceButton : Button

    {

        // A DependencyProperty and public property.

        public static readonly DependencyProperty SpaceProperty;

 

        public int Space

        {

            set

            {

                SetValue(SpaceProperty, value);

            }

            get

            {

                return (int)GetValue(SpaceProperty);

            }

        }

 

        // Static constructor.

        static SpaceButton()

        {

            // Define the metadata.

            FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata();

            metadata.DefaultValue = 1;

            metadata.AffectsMeasure = true;

            metadata.Inherits = true;

            metadata.PropertyChangedCallback += OnSpacePropertyChanged;

 

            // Register the DependencyProperty.

            SpaceProperty =

                DependencyProperty.Register("Space", typeof(int),

                                            typeof(SpaceButton), metadata,

                                            ValidateSpaceValue);

        }

 

        // Callback method for value validation.

        static bool ValidateSpaceValue(object obj)

        {

            int i = (int)obj;

            return i >= 0;

        }

 

        // Callback method for property changed.

        static void OnSpacePropertyChanged(DependencyObject obj,

                                    DependencyPropertyChangedEventArgs args)

        {

            SpaceButton btn = obj as SpaceButton;

            btn.Content = btn.SpaceOutText(btn.txt);

        }

}

 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/15123181/viewspace-422967/,如需轉載,請註明出處,否則將追究法律責任。

相關文章