WPF dependency property

WPF dependency property

WPF 提出了 dependency property 這個新型態的 property。它如名稱所說,它依靠許多 provider 來設立它最後的值。以下是它加在 .NET property 上的三個新特性:

Change notification

以往我們要寫滑鼠移到某物件上的動作時,都必需實際寫 code。比如我們要設定 MouseEnter 這個 property,指定到一個 callback function,然後在 callback function 中實現我們想要的動作。
但 dependency property 不用,它完全可以透過 XAML 來實現。像以下的程式碼:

<Button MouseEnter=”Button_MouseEnter” MouseLeave=”Button_MouseLeave”
   MinWidth=”75” Margin=”10”>OK</Button>

void Button_MouseEnter(object sender, MouseEventArgs e)
{
   Button b = sender as Button;
   if (b != null) b.Foreground = Brushes.Blue;
}

void Button_MouseLeave(object sender, MouseEventArgs e)
{
   Button b = sender as Button;
   if (b != null) b.Foreground = Brushes.Black;
}

就可以簡單的透過 trigger object 來實現:

<Trigger Property=”IsMouseOver” Value=”True”>
   <Setter Property=”Foreground” Value=”Blue”/>
</Trigger>

至於 trigger 沒有寫明 mouse leave 時要怎麼做。這邊 WPF 都會自動處理掉。

Property Value Inheritance

而 dependency property value 的值是可以繼承的。假設我們在一個 root window 中設定了某個 dependency property 的值,這個值也會被所有在 logical tree 下的 child 繼承。比如說我們設定 window font size 等於 20,那其下所有像 label, button 等的 control 其 font size 也會被設成 20。然而這個繼承概念並不是套用在所有的 dependency property。一個情況是該 dependency property 在註冊的時候就指定不繼承。另外一個情況是因為 dependency property 的值可以由許多 provider 設立。

Support for Multiple Providers

Dependency property 的值可以被許多 provider 設立,它是有優先順序的:

1. Local value
2. Style triggers
3. Template triggers
4. Style setters
5. Theme style triggers
6. Theme style setters
7. Property value inheritance
8. Default value

1 的優先權最高,8 的優先權最低。所謂 local value 指的就是透過 SetValue 等方式設定的值。而 default value 則是該 property 註冊時提供的值。


Standard Dependency Property Implementation

public class Button : ButtonBase
{
   // The dependency property
   public static readonly DependencyProperty IsDefaultProperty;
   static Button()
   {
      // Register the property
      Button.IsDefaultProperty = DependencyProperty.Register(“IsDefault”,
         typeof(bool), typeof(Button),
         new FrameworkPropertyMetadata(false,
         new PropertyChangedCallback(OnIsDefaultChanged)));
      …
   }
}

在 WPF 中,dependency property 宣告成 static field。這比傳統 .NET property 宣告成 instance field 比較不佔記憶體。在一個 class 中,無論產生的 class instance 有多少個,static field 永遠指向同一個 storage location;而 instance field 不同,class instance 有多少個,它就有多少個 storage location。

(參考:C# Language spec., 10.4.1 Static and instance fields


Attached Properties

有些 control 不支援某些 dependency property,但我們又想設定它怎麼辦呢?比如說 StackPanel 並不支援 FontSize 這個 property,但我們想透過直接設定它,來讓所有 StackPanel 的 child 都有相同的 font size。這時候可以使用 TextElement 這個 attached property:

<StackPanel TextElement.FontSize=”30” TextElement.FontStyle=”Italic”
   Orientation=”Horizontal” HorizontalAlignment=”Center”>
   <Button MinWidth=”75” Margin=”10”>Help</Button>
   <Button MinWidth=”75” Margin=”10”>OK</Button>
</StackPanel>


留言

熱門文章