2009-07-23 76 views
21

對於附加屬性如何將其值傳遞給父元素或子元素,我感到有些迷惑。 TextElement.FontFamily會導致子元素繼承分配給該屬性的值(看似下游操作,父對子)。 Grid.Column導致父項在特定位置顯示該子項(看似上游操作,子對父母)。附加屬性值如何知道是向上還是向下?我對這個錯誤的看法是錯誤的嗎?還是有一個錯誤會將所有這些置於透視之中?附加屬性在WPF中的工作原理是什麼?

<StackPanel TextElement.FontFamily="Wingdings"> 
    <Grid> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="*"/> 
      <ColumnDefinition Width="*"/> 
     </Grid.ColumnDefinitions> 

     <Button Grid.Column="1" Content="My Button"/> 
    </Grid> 
</StackPanel> 

回答

38

這裏有兩個概念:依賴項屬性附加依賴​​項屬性。 「附加屬性」是依賴屬性,支持依賴關係property value inheritance

關於基本依賴屬性,一個非常粗略的說法是,它們基本上是從wpf(邏輯/視覺)樹中的父元素繼承它們的值。如果它的metadata設置爲FrameworkPropertyMetadataOptions,則依賴項屬性(附加或不附加)將繼承其值「向下」。 繼承標誌,並且在很多情況下都是如此。

附加屬性是可以通過DependencyObject.SetValue方法在任何wpf對象上設置的屬性(基本上,至少爲 DependencyObject)。此機制的目的是「附加」到父對象所需的其他對象信息,而不是子對象本身。例如,Grid.Row是網格所需的附加屬性,用於將項目放置在其渲染區域中。

相關屬性由wpf對象系統自動「向下」繼承。

附加屬性在特定對象的代碼中顯式檢查「向上」。在網格的情況下,在確定將物品放置在何處時,它會檢查每個包含物品的Grid.Row和Grid.Column附加屬性的值。

它也常常是創建自定義附加屬性的技術,它以某種方式修改它們所連接的對象(例如,Drag'n'Drop functionality via attached properties)。

作爲附加說明,繼承附加屬性的一個很好的示例是TextElement.FontFamily。 Grid.Row和Grid.Column屬性沒有設置Inherits標誌。

TextElement.FontFamily,從反射器:

FontFamilyProperty = DependencyProperty.RegisterAttached("FontFamily", typeof(FontFamily), typeof(TextElement), new FrameworkPropertyMetadata(SystemFonts.MessageFontFamily, FrameworkPropertyMetadataOptions.Inherits | FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure), new ValidateValueCallback(TextElement.IsValidFontFamily)); 

Grid.Row,從反射器:

RowProperty = DependencyProperty.RegisterAttached("Row", typeof(int), typeof(Grid), new FrameworkPropertyMetadata(0, new PropertyChangedCallback(Grid.OnCellAttachedPropertyChanged)), new ValidateValueCallback(Grid.IsIntValueNotNegative)); 
+1

有趣且信息豐富。但是,這種情況如何:2x2網格(A)包含2x2網格(B)。網格B包含一個按鈕。如果網格B具有網格。列附加屬性設置爲1(因此它出現在其父網格的第二列中,網格A),不應該將附加屬性向下級聯到網格B的按鈕,因此按鈕會出現在網格B的第二列? – Pwninstein 2009-07-23 23:01:23

2

MSDN

雖然附加屬性是任何對象上可設置的,這並不必然意味着設置屬性將產生實際的結果,或者該值永遠不會被其他對象使用。通常,附加屬性的目的是使來自各種可能的類層次結構或邏輯關係的對象都可以將公共信息報告給定義附加屬性的類型。定義附加屬性的類型通常遵循這些模型之一:

  • 定義附着 屬性被設計成使得它可以 是元素 ,將用於設置的值的父元素的類型附 財產。該類型然後通過內部邏輯 針對某個對象樹結構迭代其 子對象, 獲取值並以某種方式對這些值執行操作。

  • 限定附 屬性的類型將被用作用於各種可能 父元素和內容模型的子 元件。

  • 定義所附 屬性的類型表示服務。其他 類型爲附加的 屬性設置值。然後,當 設置屬性的元素將在服務的 上下文中進行評估時,附加的 屬性值將通過服務類的內部邏輯 獲取。

An的實施例父定義的附加屬性

最典型的方案,其中WPF定義附加屬性是當父元素支持的子元素集合,並且還實現了一個行爲,其中行爲的具體情況將分別爲每個子元素進行報告。

DockPanel定義了DockPanel.Dock附加屬性,而DockPanel具有類級代碼作爲其渲染邏輯(特別是MeasureOverride和ArrangeOverride)的一部分。一個DockPanel實例會一直檢查它的任何直接子元素是否爲DockPanel.Dock設置了一個值。如果是這樣,則這些值將成爲應用於該特定子元素的呈現邏輯的輸入。嵌套的DockPanel實例每個處理它們自己的直接子元素集合,但是這種行爲是DockPanel處理DockPanel.Dock值的具體實現。從理論上講,可能會有影響超出直接父級元素的附加屬性。如果DockPanel。Dock附加屬性設置在一個沒有DockPanel父元素的元素上,不會引發錯誤或異常。這僅僅意味着設置了一個全局屬性值,但它沒有可能消耗信息的當前DockPanel父項。

0

簡單地說這是我的理解它(請糾正我,如果我錯了)。

對象(A)實現一個屬性,該屬性將附加到另一個對象(B)(對象B甚至不知道這個「可附加」屬性的存在)。對象B需要從DependencyObject繼承。

對象A還實現了靜態方法來檢查它在其他對象中的「可附加」屬性A.GetAttachedProperty(B)。

如果B具有來自A的附加屬性,則A.GetAttachedProperty將讀取並返回其值。否則A將嘗試讀取它,並返回null,因爲它不在那裏。