如何自訂WPF的DependencyProperty相依屬性

WPF技巧應用、相關

在WPF當中若沒有相依屬性幾乎無法做任何事情,因為您可能要重複定義許多共同的物件屬性,這不僅增加Pg許多無意義的工作且程式設計較沒有彈性。要實做WPF的相依屬性我們得在一個class中先宣告一個DependencyProperty物件,再定義一個屬性,這個屬性做為屬性變更告知之用,而透過DependencyProperty的連結,比較重要的是在相依屬性裡並不是使用我們在.NET應用程式裡慣用的get;set;的方式,而是使用在DependencyObject物件裡定義的SetValue()與GetValue()方法,如下程式:

 

   1: class ColorTextBlock: TextBlock
   2: {
   3:     public static 
   4:     readonly DependencyProperty 
   5:     BackgroundColorProperty;
   6:     public bool ChangedBackgroundColor
   7:     {
   8:         get
   9:         {
  10:             return (bool)GetValue(BackgroundColorProperty);
  11:         }
  12:         set 
  13:         { 
  14:             SetValue(BackgroundColorProperty, value); 
  15:         }
  16:     }
  17: }



筆者希望透過ChangedBackgroundColor屬性被變更為true時,將自身物件的Background改為Blue,因此必須註冊BackgroundColorProperty這個DependencyProperty,以便告訴WPF的子系統有這個相依的事件必須在這個屬性遭到變更時觸發!怎麼做呢?首先我們必須在constructor裡放置FrameworkPropertyMetadata物件存放與DependencyProperty相關的屬性資料並設定其DefaultValue屬性與PropertyChangedCallback的事件處理常式,最後註冊相依屬性ChangedBackgroundColor,程式碼如下:


 

   1: static ColorTextBlock()
   2: {
   3:     FrameworkPropertyMetadata meta = new FrameworkPropertyMetadata();
   4:     meta.DefaultValue = false;
   5:     meta.Inherits = true;
   6:     meta.PropertyChangedCallback += OnBackgroundColorPropertyChanged;
   7:     BackgroundColorProperty = DependencyProperty.Register("ChangedBackgroundColor", typeof(bool), typeof(ColorTextBlock), meta);
   8: }



如程式,要註冊DependencyProperty只要執行DependencyProperty.Register方法,傳入(引數1:相依屬性名稱,引數2:為觸發該相依屬性的屬性type,引數3:本身class的型別,引數4:PropertyMetadata物件)。OnBackgroundColorPropertyChanged的事件的實作如下: 
 

   1: static void OnBackgroundColorPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
   2: {
   3:     ColorTextBlock ctb = obj as ColorTextBlock;
   4:     ctb.Background = Brushes.Blue;
   5: }



這裡所傳入的DependencyObject即是ColorTextBlock物件,而這個事件只有當屬性ChangedBackgroundColor被變更時會觸發,所以筆者只是將背景設為Blue而已,要測試此程式我們可以在Grid_Load裡加入如下:


 

   1: private void Grid_Loaded(object sender, RoutedEventArgs e)
   2: {
   3:     ColorTextBlock ctb = new ColorTextBlock();
   4:     ctb.Text = "abcdefghijk";
   5:     ctb.HorizontalAlignment = HorizontalAlignment.Left;
   6:     ctb.VerticalAlignment = VerticalAlignment.Top;
   7:     ctb.ChangedBackgroundColor = true;
   8:     Grid1.Children.Add(ctb);
   9: }



程式的行結果如下:

若將ctb.ChangedBackgroundColor = true 這行拿掉底色就不會變成藍色,這點讀者可以自行測試看看。

而將ctb.ChangedBackgroundColor設定為false底色也不會改變這是因為我們對這個DependencyProperty的DefaultValue屬性給的是false,所以您再塞false進去當然對於系統而言屬性不算是被變更!所以不會觸發OnBackgroundColorPropertyChanged 這個事件。


 

簽名:

學習是一趟奇妙的旅程

這當中,有辛苦、有心酸、也有成果。有時也會有瓶頸。要能夠繼續勇往直前就必須保有一顆最熱誠的心。

軟體開發之路(FB 社團)https://www.facebook.com/groups/361804473860062/

Gelis 程式設計訓練營(粉絲團)https://www.facebook.com/gelis.dev.learning/


 

如果文章對您有用,幫我點一下讚,或是點一下『我要推薦,這會讓我更有動力的為各位讀者撰寫下一篇文章。

非常謝謝各位的支持與愛護,小弟在此位各位說聲謝謝!!! ^_^