2009年4月30日 星期四

[WPF] 相依屬性(Dependency Property) 進階探討

實作 Dependency Property(相依屬性) 的規則與流程

1、首先必須宣告 Dependency Property

Dependency Property 欄位都是 publicstatic,並且名稱以「Property」作為結尾。

例如以下宣告:
public static readonly DependencyProperty IsDefaultProperty;

2、在 static 建構子中註冊 Dependency Property

由於 Dependency Property 必須呼叫 static 方法 DependencyProperty.Register() 來建立

而在註冊時,必須在 Register() method 中指定以下內容:
  • Dependency Property 的名稱

  • Dependency Property 的型態

  • 包含 Dependency Property 的 Class 型態

  • Metadata (型態為 FrameworkPropertyMetadata,而 Callback Function 宣告於此處)

  • 用來檢查 Property 的值是否合法的 function


3、設定 Getter 與 Setter

Dependency Property 宣告了就是用來設定或取值之用的,當然要設定 Getter 與 Setter 囉!

但比較特別的是,Dependency Property 值的設定或取得,是透過 System.Windows.DependencyObject 中的 SetValue()GetValue() 來處理的。

而比較需要注意的是,若是有任何的程式邏輯或是檢查要加入,請記得加到 Callback Function 中,別加在 Getter 與 Setter 中,因為那只是用來取值或設定值之用。
(所有 WPF 內建的屬性封裝都遵守此規則,因此別亂寫囉!)



使用 Dependency Property 的優點 & 所提供的功能

1、節省記憶體

想像一下,Button 類別有將近 100 個欄位值,每個 Label 也將近有 90 個欄位值,若是畫面中有一堆 Button 與 Label 所產生的物件,記憶體的耗用量豈不是很可觀?

沒錯,這就是 Dependency Property 所要解決的問題,透過 static 的方式先產生 Dependency Property,在將 Button 與 Label 物件的屬性「依附上去」。

當每個 Button 或是 Label 都依附到同一個 Dependency Property,如此一來,記憶體的用量就會大大地減少囉!


2、變更告知 (Change Notification)

WPF 可以根據 Dependency Property 的 Metadata 自動觸法許多動作,例如:重新整理元素、更新畫面配置、重新整理資料繫結...等等。

範例:以下程式實作滑鼠移到按鈕上後,更改文字顏色(Button 的 IsMouseOver 屬性被更改,自動觸發更改文字顏色)

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="About WPF Unleashed" SizeToContent="WidthAndHeight" Background="OrangeRed" FontSize="30" FontStyle="Italic">





Chapter 1
Chapter 2








You have seccessfully registered this product.





3、屬性值繼承 (Property Value Inheritance)

元素樹中,父節點的控制項屬性會向下套用到子系的控制項屬性。

但也是有些例外的情況,原因可能會有兩種:
  1. 在 DependencyProperty.Register() 裡,透過 FrameworkPropertyMetadata.Options.Inherits 設定為不繼承父系控制項的屬性值。

  2. 子系控制項覆寫了繼承來的屬性值。


4、支援多重提供者

WPF 中有許多屬性提供者可用不同的方式設定 Dependency Property,而屬性值的決定過程會經過五個步驟:
  1. 判斷基底值

    這個部分會由多種屬性提供者來提供值,優先順序為:

    Local Value -> Style Trigger -> Template Trigger -> Style Setter -> Theme Style Trigger -> Theme Style Setters -> Property Value Inheritance -> Default Value

  2. 驗算

    此部份進行屬性值的驗算,為運算式。

  3. 套用動畫

    若有一個以上的動畫正在執行,它們可以改變目前的屬性值,甚至完全置換掉。

  4. 轉換

    若有註冊 CoerceValueCallback 委派,則屬性值會被傳遞到此 function 進行轉換,以取得更新後的值。
    (例如 ProgressBar 就是利用 callback function 來保持屬性值不會超過最大或最小值)

  5. 驗證

    最後還會進行屬性值的驗證,決定該值是否合法。(若有設定 ValidateValueCallback 委派)


5、附加屬性 (Attached Property)


附加屬性(attached property)是種特殊的 Dependency Property,可以附加到任何物件上,以下直接用範例說明:

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="About WPF Unleashed" Background="OrangeRed">





Chapter 1
Chapter 2








You have seccessfully registered this product




從程式碼可以看出,透過附加屬性的使用,StackPanel 中的控制項就不用一一加上 FontSize & FontStyle 兩個屬性了。


參考資料

Anita 的.NET 世界: 什麼是Dependency Property

design studio: Dependency Property

WPF Tutorial | Introduction to DependencyProperties

1 則留言:

  1. Are you looking to earn cash from your websites with popup ads?
    If so, did you try using PopCash?

    回覆刪除