2010-06-25 236 views
18

我一直在閱讀有關依賴屬性的幾本書,但都有一個共同點,他們只是告訴我們它們是如何實現的(使用static readonly DependencyProperty等),但沒有告訴他們從內部工作的確切方式。依賴屬性WPF

我的意思是它們是作爲靜態實現的,但仍適用於所有對象。
混淆的第二點是附加屬性。

是否有任何教程可以通過簡單的方式解釋所有這些概念?

回答

30

我的依賴屬性是如何工作的心理模型:

任何DependencyObject類實現兩個特殊的屬性。其中,該類的靜態屬性是一個DependencyProperty對象的字典。每個類的實例都可以在該字典的內部查找有關每個DependencyProperty的元信息 - 屬性的名稱,類型,必須在獲取和設置時調用的任何回調,它如何參與屬性繼承等等。當你註冊一個依賴屬性時,你正在爲這個字典添加一個條目。

的其他財產是一個實例屬性:它是一本字典,通過DependencyProperty鍵,包含每個DependencyProperty的地方,如果它已經被設置。

SetValueGetValue你在CLR屬性的setter和getter中實現的方法基本上是對類固醇的惰性評估。它們不是在後臺字段中存儲和檢索屬性的值,而是在值字典中存儲和檢索屬性的值。

依賴項屬性的神奇之處在於GetValueSetValue實際上是做什麼的。

GetValue查找對象值字典中屬性的值。如果它沒有找到它,它會在父元素上調用GetValue,以獲取父元素認爲值是什麼。例如,當您在Window中創建TextBox時,看到TextBoxFontFamily的任何內容實際上都是調用GetValue。除非您已明確設置字體,否則其字典中沒有該屬性的條目。所以GetValue要求父元素的值。父元素可能有也可能沒有FontFamily集;如果不是,呼叫GetValue返回從它的親的價值。依此類推,直到達到Window對象,並找到實際的FontFamily值。

如果您在TextBox上設置了FontFamily,SetValue將值存儲在值字典中。在下一次需要獲得的FontFamily的值時,GetValue將在字典中找到該值並將其返回,因此它不需要詢問父元素。

如果您在Window設置FontFamilySetValue不僅更新Window的價值字典中的值,它觸發關閉一個屬性更改事件,一切都依賴於財產聽到。 (這就是爲什麼他們被稱爲依賴屬性,請記住。)如果依賴於屬性的東西本身就是一個依賴屬性,它會觸發它自己的屬性更改事件。這是如何更改Window上的FontFamily更改窗口中每個控件的字體,並且還提示WPF重新呈現已更改的控件。

附加屬性使用相同類型的方法工作。任何可以附加屬性的對象都有一個字典,用於存儲附加屬性的值。當您在XAML中的CheckBox上設置Grid.Column時,您只需向該CheckBox的字典中添加條目即可。當Grid需要知道CheckBox所在的列時,它會查看該字典中的值。當您在對象上設置Grid.IsSharedSizeScopeTrue時,該對象的字典將包含一個新屬性 - 一個包含每個SharedSizeKey的寬度/高度的字典。

我應該強調這是我的心智模式。我沒有坐下來看反光板,看着實際實施Register,GetValue,和SetValue找出他們如何實際工作。我可能對細節有誤。但是,這是一個準確預測這些東西的行爲的模型,所以它足夠好。

在字典中存儲屬性值的概念對C#程序員來說很奇怪。儘管如此,這對Python程序員來說仍然是一個老帽子。在Python中,所有的類屬性 - 實際上所有的對象 - 都存儲在字典中,所以你可以通過屬性訪問器或者通過查看它們來獲得它們的值。 .NET依賴屬性和附加屬性是竊取所有值得竊取的Java的另一種方式,現在正在掠奪Python。 (或者從Python掠奪他們的任何地方。)學習Python使我成爲一個更好的C#程序員;我把它推薦給尚未完成的任何C#開發人員。

+0

羅伯特,這麼多感謝您的精彩explaination.I現在可以想像他們怎麼幹活不明白附加屬性properly.Here是我的理解:複選框具有由靜態property.That詞典鍵控字典可以有鍵控值對於該複選框has.But它也可以包含通過。當電網想知道關於它的位置,它看起來由電網鍵條目其他對象的靜態屬性(Grid.Column)(網格)鍵入其他值的所有屬性.COLUMN和Grid.Row並使用it.So我們可以爲Grid.Column增加,即使它在網格內沒有一個條目。 – 2010-06-27 06:02:19

+0

羅伯特,我對不對? – 2010-06-27 08:18:05

+3

正確的聲音,我,但「那本詞典可以有鍵值,爲所有的複選框具有屬性」應該說「依賴屬性」。另外我應該指出,當我寫了上面的帖子時,我被誤解爲附加屬性是像依賴屬性這樣的機制;實際上,附加屬性*是*依賴屬性。 – 2010-06-27 18:51:47

6

一些附加informatin這裏是依賴屬性http://www.wpftutorial.net/DependencyProperties.html一個教程,說明他們是如何工作的一點點。

DependencyProperty對象爲什麼在靜態字段中的簡短說明是它代表屬性的描述而不是屬性的值。每個DependencyObject都有一個從DependencyProperty對象到它們的值的映射。

這也是如何附加屬性的工作。因爲每個DependencyObject正在存儲從任何DependencyProperty到一個值的映射,所以任何類型都可以創建一個新的DependencyProperty並將其設置在任何現有的DependencyObject上。

0

您可以在下面看到dependency property的一個非常基本的示例,該示例創建了一個custom control text box,其中空格將不被允許表示用戶無法在文本框中輸入空格。

1)創建的ValidatedTextBox名稱的類,並寫在這個類文件下面的代碼:

public class ValidatedTextBox : TextBox 
{ 
    public ValidatedTextBox() 
    { 
    } 

    public static readonly DependencyProperty IsSpaceAllowedProperty = 
     DependencyProperty.Register("IsSpaceAllowed", typeof(bool), typeof(ValidatedTextBox)); 

    public bool IsSpaceAllowed 
    { 
     get { return (bool)base.GetValue(IsSpaceAllowedProperty); } 
     set { base.SetValue(IsSpaceAllowedProperty, value); } 
    } 

    protected override void OnPreviewKeyDown(KeyEventArgs e) 
    { 
     base.OnPreviewKeyDown(e); 
     if (!IsSpaceAllowed && (e.Key == Key.Space)) 
     { 
      e.Handled = true; 
     } 
    } 
} 

2)現在使用上述控制到您.XAML文件

一)添加命名空間自定義控件文本框的象下面這樣:

xmlns:CustomControls="clr-namespace: ValidatedTextBox;assembly= ValidatedTextBox " 

b)現在,使用自定義控制文本框象下面這樣:

<CustomControls:ValidatedTextBox IsSpaceAllowed="False" x:Name="MyTextBox" /> 

這將創建一個自定義的控制文本框,將不會允許的空間。因此,基本依賴屬性允許添加功能,擴展任何控件的功能。