書名:WPF專業(yè)編程指南
作者:李應(yīng)保
出版社:電子工業(yè)出版社
出版時(shí)間:2010-01
ISBN:9787121100116
一、附加屬性
- 附加屬性(Attached Property)其實(shí)是相關(guān)屬性的另外一種形式。
所有從DependencyObject類中派生出來的類,都可以使用附加屬性。
二、引入附加屬性的原因
- 為什么要引入附加屬性呢?
可以看這樣一個(gè)例子:若有一些圖形,比如說矩形,要在視窗上顯示出來。
若使用Canvas排版,那么要告訴Canvas該矩形的左上角坐標(biāo)。
一種實(shí)現(xiàn)方式是定義一個(gè)基類,其中含有x,y坐標(biāo),然后把具體的圖形類從該基類中派生出來,這樣所有的圖形在Canvas上的位置就確定了。
然而,這種解決方案,在WPF中會(huì)行不通:WPF支持多種排版。
比如說,同樣的圖形元素,現(xiàn)在要改在Grid上顯示了,這時(shí),就不能使用左上角x,y坐標(biāo),而要指出圖形在Grid中的行列號(hào)。
又如,同樣的圖形要在DockPanel中顯示時(shí),所要給出的居然是Top、Left、Right或Bottom這樣的相對(duì)位置。顯然,由于WPF排版的多樣性,過去所用的解決問題的方法已經(jīng)不夠用了。
三、解決辦法
WPF引入了附加屬性來解決這個(gè)問題:圖形元素,比如矩形,就不需要預(yù)先說明它們?cè)诖翱趦?nèi)的位置,當(dāng)要在某個(gè)特定的排版環(huán)境中顯示時(shí),可以把排版類的某些相關(guān)屬性引入進(jìn)來,從而確定自己在窗口中的位置。
在Grid中顯示矩形的例子如下:
<Window x:Class="Yingbao.Chapter4.AttachedPropertyExample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Yingbao.Chapter4" Height="300" Width="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height ="*"/>
<RowDefinition Height ="2*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width ="*"/>
<ColumnDefinition Width ="2*"/>
</Grid.ColumnDefinitions>
<Rectangle Stroke ="Aqua" Fill ="Brown " Grid.Column ="0"
Grid.Row ="0"/>
<Rectangle Stroke ="Blue" Fill ="Yellow " Grid.Column ="1"
Grid.Row ="0"/>
<Rectangle Stroke ="Aqua" Fill ="Brown " Grid.Column ="1"
Grid.Row ="1"/>
<Rectangle Stroke ="Blue" Fill ="Yellow " Grid.Column ="0"
Grid.Row ="1"/>
</Grid>
</Window>
-
本例定義了一個(gè)2行2列的Grid,用4個(gè)矩形填充這4個(gè)網(wǎng)格;
每個(gè)矩形在Grid中的位置,是由Grid.Column和Grid.Row確定的。
顯然,這里的Grid.Column和Grid.Row不是矩形的屬性,而是Grid的屬性。
為什么可以把Grid的屬性用到矩形Rectangle中來呢?
難道WPF有什么魔法不成?
在Grid中顯示的矩形如圖4-5所示。
圖4-5 在Grid中顯示矩形 -
問題的關(guān)鍵在于Rectangle類具有DependencyObject作為它的基類,圖4-6是矩形Rectangle類在WPF中的完整類繼承樹,由圖4-6可見,DependencyObject是其中的一個(gè)基類,換句話說,Rectangle是DependencyObject(這是UML的通常表述)。
圖4-6 WPF中矩形(Rectangle)的繼承樹 當(dāng)我們?cè)赬AML中使用下面的語句時(shí):
<Rectangle Stroke ="Aqua" Fill ="Brown " Grid.Column ="0" Grid.Row
="0"/>
設(shè)置Grid.Column=“0”,實(shí)際上調(diào)用的是DependencyObject中的(Grid.Column, “0”)方法。
類似地,要讀取附加屬性的值,可以調(diào)用DependencyObject中的GetValue方法。
筆者認(rèn)為DependencyObject中應(yīng)該有一個(gè)維護(hù)相關(guān)屬性和值之間的哈希表。
由此可見,要把相關(guān)屬性引入到某個(gè)類中,這個(gè)類必須是DependencyObject,這一點(diǎn)非常重要。其次,如要使相關(guān)屬性能被引入到DependencyObject類中,則一定要在注冊(cè)該相關(guān)屬性時(shí)。注冊(cè)相關(guān)屬性為附加屬性的方法是調(diào)用DependencyProperty類中的RegisterAttached方法。

