WPF裡的DependencyProperty(1)

來源:互聯網
上載者:User

自己一個人學東西,怎麼樣才算會了?除了做東西,有兩個檢驗的辦法,第一是去給不懂的人講,看看能不能把別人講明白了,第二是寫文章,看看理不理的清楚思路 呵呵
第一次嘗試寫些東西,,先在這兒貼出來再說~
不廢話了,今天先發第一部份
一 引入DependencyProperty

這個概念可以說是WPF核心中的核心了。在WPF的架構中隨時都能見到它的身影。關於DependencyProperty能帶來的諸多方便,很多介紹性的文章裡都有,我這裡就不介紹了,今天先從什麼是DependencyProperty說起。

從屬性開始屬性

在CLR中有屬性(Property)這個概念,它可以用來封裝欄位。

private string _myString;
public string MyString
{
get{return _myString;}
set{_myString=value;}
}

這種屬性應用的非常多,我們還可以在set或get方法中加入某些邏輯,確定讀取或者設定屬性的值的時候我們是不是需要某些其他的判斷,一個經典的例子是在Age屬性的set方法中加入對年齡範圍的判斷。這些就不多說了。

但是WPF架構的編程經常和介面打交道,經常遇到的一個情況是某個屬性的值的變化會影響到多個其他對象。比如當一個Button的改變大小超過了它的容器,他的容器應該自動調整大小。於是我們考慮在每個屬性的set方法中觸發一些事件,但很快我們發現現有的功能很難滿足我們的需求,至少不能簡潔漂亮的滿足這些需求。
實際上我們的需求更加複雜,WPF中的資料繫結,XAML文法等很多地方都和屬性密切相關,我們迫切需要一種功能更加強大的屬性。

於是在WPF中,引入了一種特殊的屬性,Dependency Property。這種屬性和普通的屬性最大不同在於,它的值的來源並不單一。對這種屬性的取值和賦值都會能與其他對象有影響,因此能得到很大的靈活性。

這很抽象,也許很難懂。不明白不要緊,先接著看。一步步來,先看看DependencyProperty長什麼樣,從定義DependencyProperty開始:

public static readonly DependencyProperty MyStringProperty = DependencyProperty.Register(
"MyString",
typeof(string),
typeof(ClassMyDependency),
new PropertyMetadata("defaultValue", new PropertyChangedCallback(onMyStringPropertyChange)));

一眼看上去很複雜,首先使用public static readonly的方式(其實就是設計模式裡的單鍵 這是.net裡的一種簡單實現)定義了一個全域的DenpendencyProperty成員,這個成員的值通過DependencyProperty的Register方法獲得,這個成員我們稱做DependencyProperty標識。

我們傳入了一些參數,分別表示屬性名稱,屬性類型,父元素(也就是包含屬性的元素)類型,屬性中繼資料(這些以後再詳細介紹)。
要注意的是, 雖然我們定義的名稱是MyStringProperty,但是屬性的名稱不是成員的名稱,它由第一個參數指定.這個Property的尾碼不是可選的,雖說不按照這個規則編譯能通過,但是.net中很多地方都遵循了這種規則,這裡我們瞭解這個規則並保證自己定義的DependecyProperty都遵循它就行了,以後會有更詳細的解釋.
實際上我們得到了一個屬性的標識,這個資料是全域的且是唯一確定的,當需要訪問屬性的值時,只需要調用對象的GetValue()和SetValue()方法來訪問()。文法是:

GetValue(property)
SetValue(property, value)

方法的調用者,不僅可以是定義DependencyProperty的對象,它可以是任何繼承了DependencyObject的對象,換句話說,這個屬性定義在了這裡,但是它並不完全屬於這個對象。這很不好理解,不過也正是DependencyProperty功能的強大之處之一,現在先不必深究這個。
不過使用GetValue和SetValue方法給屬性賦值讓我們很不習慣,於是我們可以對這兩個方法進行封裝,在上面DependencyProperty的定義之後加上:

public string MyString
{
get { return (string)GetValue(myStringProperty); }
set { SetValue(myStringProperty, value); }
        }

這在MSDN中稱為”CLR封裝(wrapper)”,這是可選的,不過經過封裝之後,這樣對於外界來說,DependencyProperty就和傳統屬性沒有什麼區別了,實現了完全的“向下相容”。

雖然我們還不很清楚DependencyProperty到底可以用來做什麼,但現在為止至少已經實現了傳統屬性的所有功能,注意到,我們並沒有定義那個private的私人欄位。實際上,.net自動為我們建立了用來儲存屬性值的地區,這是一種基於Hash的資料存放區機制,效率肯定低於傳統屬性,不過這些效率損失不足以影響我們。插一句,犧牲一點點效能來換取強大的功能是DotNet的一貫做法,呵呵

關於為DependencyProperty的賦值,實際上和傳統的屬性沒有太大區別,XAML和 code中都可以為其賦值:
code中就不介紹了,和傳統屬性賦值相同,在XAML中,使用一個XML屬性即可:
<l:ClassMyDependency MyString="11111" MyString1="22222" x:Key="myclass" />

l是實現定義的名字空間首碼,MyString是一個DependencyProperty,MyString1是一個普通屬性,實際上這兩個屬性都能實現XAML下的賦值。
這一句XAML如果翻譯成C# code大概是這個樣子:

        ClassMyDependency myclass = new ClassMyDependency();
        myclass.MyString="11111";
        mycalss.MyString1="22222";

網上有一些地方介紹說DependencyProperty主要功能是為了能讓XAML代碼為後台屬性賦值,這是錯誤的。
不過使用XAML使用DependencyProperty也是有道理的。至於具體為什麼,我準備在後續的POST裡面會詳細的說明。

好了,就這麼多。今天的第一篇裡,我們看到了DependencyProperty的樣子,大概瞭解它的定義,它的儲存方式。不過事實上我們到現在還並不知道這到底能用在什麼地方。下一篇POST中我準備介紹一下DependencyProperty的一些用途,並且從用途出發看看一下它是如何完成這些看似有點不可思議的功能的。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.