依賴屬性就是一種可以自己沒有值,并能通過使用Binding從數據源獲得值(依賴在別人身上)的屬性。擁有依賴屬性的對象稱為“依賴對象”。
WPF開發中,必須使用依賴對象作為依賴屬性的宿主,使二者結合起來。依賴對象的概念被DependencyObject類所實現,依賴屬性的概念則由DependencyProperty類所實現
從這棵繼承樹上可以看出,WPF的所有UI空間都是依賴對象。
看最簡單的依賴屬性
class Student : DependencyObject { public string Name { get { return ( string )GetValue(NameProperty); } set { SetValue(NameProperty, value); } } public static readonly DependencyProperty NameProperty = DependencyProperty.Register( " Name " , typeof ( string ), typeof (Student)); }
實例并非使用new操作符得到而是使用DependencyProperty.Register方法生成。
現在我們使用的Register方法是參數最少,最簡單的一個重載,我們來分析一下
- 第一個參數為string類型,表示指明以哪個CLR屬性作為這個依賴屬性的包裝器。就是代碼
public string Name { get { return ( string )GetValue(NameProperty); } set { SetValue(NameProperty, value); } }
- 第二個參數指明此依賴屬性用來存儲什么樣的值。
- 第三個參數用來指明此依賴屬性的宿主是什么類型,或者說DependencyProperty.Register方法要將這個依賴屬性注冊到哪個類型上。
注意 :1.依賴屬性包裝器是一個CLR屬性,并不是依賴屬性,沒有包裝器,依賴屬性依舊存在。
???????? 2.既然沒有包裝器依賴屬性也存在,那么包裝器是干什么用的呢?包裝器的作用是以“實例屬性”的形式向外界暴露依賴屬性,這樣,一個依賴屬性才能成為數據源的一個Path。
???????? 3.注冊依賴屬性時使用的第二個參數是一個數據類型,這個數據類型也是包裝器的數據類型。
請看例子
< Window x:Class ="DependencyPropertySample.MainWindow" xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml" Title ="MainWindow" Height ="350" Width ="525" > < StackPanel > < TextBox x:Name ="textbox1" BorderBrush ="Black" Margin ="5" /> < TextBox x:Name ="textbox2" BorderBrush ="Black" Margin ="5" /> < Button Content ="OK" Margin ="5" Click ="Button_Click" /> </ StackPanel > </ Window >
public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void Button_Click( object sender, RoutedEventArgs e) { Student stu = new Student(); stu.SetValue(Student.NameProperty, textbox1.Text); textbox2.Text = ( string )stu.GetValue(Student.NameProperty); } }
當第一次看到這個例子的時候,也許會有點百思不得其解的感覺——依賴屬性不是一個Static對象么?哪怕有1000個Student實例,依賴屬性只有一個啊,那么SetValue把值存儲到哪里去了?GetValue又從哪里讀取值?并且,依賴屬性不是一個只讀的嗎?怎么可以寫入值呢? 其實這個問題直指依賴屬性機制的核心,我們過一會再討論。
還要注意一點,盡管student類沒有實現INotifyPropertyChange接口,當屬性的值發生改變時與之關聯的Binding對象依然可以得到通知,依賴屬性默認帶有這樣的功能,天生就是合格的數據源。
使用vs2010有一個小技巧,生成依賴屬性可以使用代碼段propdp,DependencyProperty.Register帶4個參數,第四個參數的類型是PropertyMetadata類,作用是給依賴屬性的DefaultMetadata屬性賦值。顧名思義,DefaultMetadata的作用就是向依賴屬性的調用者提供一些基本信息,這些信息包括:
- CoerceValueCallback :依賴屬性的值被強制改變時此委托會被調用,此委托可關聯一個函數。
- DefaultValue :依賴屬性未被顯示賦值時,若讀取之則獲得此默認值,不設置此值會拋出異常。
- IsSealed :控制PropertyMetadata的屬性值是否可以更改,默認值為true。
- PropertyChangeCallback :依賴屬性的值被改變之后此委托會被調用,此委托可關聯一個函數。
注意:依賴屬性的DefaultMetadata只能通過Register方法的第四個參數驚醒賦值,而且一旦賦值就不能改變。如果想用新的PropertyMetadata替換這個默認的Metadata,需要使用DependencyProperty.OverrideMetadata方法。
下面我們來解決剛才的紅色問題。
首先值存到什么地方去了?
創建一個DependencyProperty實例并用它的CLR屬性名和宿主類型名生成hash code,最后把hash code和DependencyProperty實例作為Key-Value對存入全局的,名為PropertyFormName的Hashtable中。
。。。(我認為書上寫的太深奧啦,想要深究的同學可以參考《深入淺出WPF》)
初學者不必深究,那就是使用了static和readonly是為了保證DependencyProperty的索引值唯一。真正的值是存在一個Hashtable中的,當然可讀可寫啦。
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
