1. 程式人生 > >介紹WPF中DependencyProperty的一些基本用法

介紹WPF中DependencyProperty的一些基本用法

在程式中使用DependencyProperty好的,我相信你已經決定了要使用DependencyProperty而不是傳統的CLR屬性,正如上一篇Post所說,很多地方都需要使用到DependencyProperty,作為例子,我決定定義一個MyBorderEx,在WPF常用的”Border”控制元件中建立一個名為Transparency的屬性,來指示它的透明度,這個屬性值在0-255間變化,255表示全透明,0表示完全不透明。
我們首先定義這個DependencyProperty:

public readonly static DependencyProperty TransparencyDependency =
DependencyProperty.Register(
“Transparency”,
typeof(Double),
typeof(MyBorderEx)
);
public Double Transparency
{
get { return (Double)GetValue(TransparencyDependency); }
set { SetValue(TransparencyDependency, value); }
}
這是標準的定義方式,首先定義了一個靜態的DependencyProperty變數。然後封裝了Transparency屬性,這樣可以完成向前相容,MSDN中稱為”CLR Wapper”。
我們只是定義了這個屬性,不過這個屬性更改時還不會自動的去更新MyBorderEx的透明度,其實WPF中包含有一個預設的名為Opacity的屬性來完成這個工作,我們就借用他來實現這個功能。也許你會想這麼做。

public Double Transparency
{
get { return (Double)GetValue(TransparencyDependency); }
set
{
SetValue(TransparencyDependency, value);
Opacity = 1 - ((double)value / 255);
}
}
如果這是傳統的屬性,也許我們只有這麼做了,但是如果你使用這種做法的話,只有在手動改變”Transparency”的值也就是呼叫了Set方法時才會更新Border的Opacity屬性,但是如果在XAML程式碼中改變Transparency屬性,WPF是不會呼叫Set方法的,因此這時類似下面的程式碼會沒有效果。


實際上,當你使用類似 Transparency=”50” 這樣的語法時,WPF會直接通過”Transparency”字串,直接尋找到這個DependencyProperty的值(還記得Register的時候我們傳了一個”Transparency”過去嗎,值就是根據這個字串找到的),然後更改這個DependencyProperty的值。

一種解決方式如下,DependecyProperty提供了屬性改變通知的功能,我們可以利用DependencyProperty的這個功能,定義一個transparencyPropertyChangedCallback函式,在屬性值變化(注意,這裡指DependencyProperty的值發生變化而不是我們定義的”CLR wapper”的Transparency屬性)時修改Opacity屬性。我們現在先這樣做,後面的Post中我會使用更漂亮(正統)的方式解決這個問題,完整程式碼如下:

class MyBorderEx:Border
{
public MyBorderEx()
{
//初始化時預設給定一個背景色
Background = Brushes.Blue;
}
public readonly static DependencyProperty TransparencyDependency =
DependencyProperty.Register(
“Transparency”,
typeof(Double),
typeof(MyBorderEx),
new PropertyMetadata(new PropertyChangedCallback(transparencyPropertyChangedCallback))
);

static void transparencyPropertyChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
MyBorderEx border = (sender as MyBorderEx);
if (border != null)
{
border.Opacity =1 - Convert.ToDouble(e.NewValue) / 255;
}
}

public Double Transparency
{
get { return (Double)GetValue(TransparencyDependency); }
set { SetValue(TransparencyDependency, value); }
}
}

主窗體中的XAML呼叫程式碼:


很有意思的是,XAML中改變屬性的值,並又不是通過Transparency屬性的set方法,你可以在Transparency的set方法中設定斷點或寫一些其他程式碼,這些程式碼並不會被執行。但是,這裡你並不能刪除看似沒什麼用處的Transparency屬性,也就是所謂的”CLR Wapper”,甚至你不能刪除這個不會被執行到的set方法。否則XAML呼叫中會報錯。

為了證明以上結論,你可以試著把set方法中的那行SetValue(TransparencyDependency, value); 去掉,程式依然正常執行。但是如果你移除了整條set方法,編譯會不通過。

好,我們把程式碼還原,這樣已經就完成了一個DependencyProperty的定義,下面我們給這個小程式加上兩個功能。

前面提到過,使用了DependencyProperty的屬性可以用作資料繫結目標,我們在Window上放一個Slider測試一下資料繫結效果。目標:使用Slider動態改變Border的透明度,我全部使用XAML實現,只有很簡單的兩行程式碼