2009-07-23 6 views
21

Ich bin ein wenig verwirrt darüber, wie angefügte Eigenschaften ihre Werte entweder Eltern oder Kind Elemente übermitteln. TextElement.FontFamily bewirkt, dass untergeordnete Elemente den dieser Eigenschaft zugewiesenen Wert erben (eine scheinbar nachgelagerte Operation, übergeordnetes untergeordnetes Element). Grid.Column bewirkt, dass ein übergeordnetes Element dieses untergeordnete Element in einer bestimmten Position anzeigt (eine scheinbar vorgelagerte Operation, untergeordnetes Element). Wie können angehängte Eigenschaftswerte entweder nach oben oder nach unten fließen? Ist meine Vorstellung davon falsch oder fehlt ein Stück, das all dies relativiert?Wie genau funktionieren angefügte Eigenschaften in WPF?

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

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

Antwort

38

Es gibt zwei Konzepte hier: Abhängigkeitseigenschaften und verbundenen Abhängigkeitseigenschaften. "Angehängte Eigenschaften" sind Abhängigkeitseigenschaften und unterstützen daher die Abhängigkeit property value inheritance.

Über grundlegende Abhängigkeitseigenschaften wäre eine sehr grobe Aussage, dass sie ihre Werte grundsätzlich von übergeordneten Elementen im wpf (logisch/visuell) Baum erben. Eine Abhängigkeitseigenschaft (angehängt oder nicht) erbt ihren Wert "abwärts", wenn ihre metadata mit der FrameworkPropertyMetadataOptions festgelegt ist. Inherit Flag, und in vielen Fällen ist dies so.

Befestigt Objekte sind Objekte, die auf jedem Objekt WPF eingestellt werden können (im Allgemeinen, mindestens a DependencyObject) über die DependencyObject.SetValue Methode. Der Zweck dieses Mechanismus besteht darin, andere Informationen, die von übergeordneten Objekten benötigt werden, an "andere Objekte" anzuhängen, nicht die untergeordneten Objekte selbst. Beispielsweise ist die Grid.Row eine angefügte Eigenschaft, die von dem Raster benötigt wird, um Elemente in seinem Wiedergabebereich zu platzieren.

Abhängigkeitseigenschaften werden vom wpf-Objektsystem automatisch "nach unten" vererbt.

Angehängte Eigenschaften werden explizit im Code bestimmter Objekte "nach oben" untersucht. Im Fall von Grid prüft es bei der Bestimmung, wo seine Elemente platziert werden sollen, nach dem Wert der angefügten Eigenschaften Grid.Row und Grid.Column für jedes enthaltene Element.

Es ist auch oft die Technik, um benutzerdefinierte angefügte Eigenschaften zu erstellen, die in irgendeiner Weise die Objekte ändern, denen sie zugeordnet sind (z. B. Drag'n'Drop functionality via attached properties).

Als eine zusätzliche Anmerkung ist ein gutes Beispiel für eine geerbte angefügte Eigenschaft TextElement.FontFamily. Grid.Row- und Grid.Column-Eigenschaften haben das Inherits-Flag nicht festgelegt.

TextElement.FontFamily, von Reflektor:

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

Grid.Row, von Reflektor:

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

Interessant und informativ. Was aber ist mit diesem Szenario: Ein 2x2 Grid (A) enthält ein 2x2 Grid (B). Grid B enthält einen Button. Wenn Grid B sein Grid hat.Column Attached Property auf 1 gesetzt (so erscheint es in der zweiten Spalte des übergeordneten Rasters, Grid A), sollte diese Attached-Eigenschaft nicht nach unten auf den Button von Grid B kaskadieren, sodass der Button in der zweiten Spalte von Grid B erscheint? – Pwninstein

+1

Gute Frage, fügte Informationen zu der Antwort hinzu. –

+0

Super! Macht jetzt viel mehr Sinn, danke !! – Pwninstein

2

Von MSDN:

Obwohl angebracht Eigenschaften einstellbar für jedes Objekt sind, die nicht automatisch bedeuten, dass die Eigenschaft Einstellung wird ein greifbares Ergebnis führt, oder dass der Wert jemals von einem anderen Objekt verwendet werden. Im Allgemeinen sind angefügte Eigenschaften so vorgesehen, dass Objekte, die aus einer Vielzahl möglicher Klassenhierarchien oder logischer Beziehungen stammen, gemeinsame Informationen an den Typ melden können, der die angefügte Eigenschaft definiert. Der Typ, die beigefügte Eigenschaft definiert folgt typischerweise eines dieser Modelle:

  • der Typ, der die angeschlossene definiert Eigenschaft so ausgelegt ist, dass es das Mutterelement der Elemente sein kann , die Werte für den Satz wird beigefügt Eigentum. Der Typ iteriert dann seine untergeordneten Objekte durch die interne Logik gegen eine Objektbaumstruktur, erhält die Werte und wirkt auf diese Werte in irgendeiner Weise.

  • Der Typ, die beigefügten Eigenschaft definiert wird für eine Vielzahl von möglichen geordneten Elementen und Inhaltsmodellen als Kind Element verwendet werden.

  • Der Typ, der die angehängte -Eigenschaft definiert, stellt einen Dienst dar. Andere Typen legen Werte für die angehängte -Eigenschaft fest. Wenn das Element , das die Eigenschaft festlegt, im Kontext des Dienstes ausgewertet wird, werden die zugehörigen Eigenschaftswerte über die interne Logik der Serviceklasse abgerufen.

Ein Beispiel für ein Eltern-Defined Befestigt Property

Das typischste Szenario, in dem WPF eine angebaute Eigenschaft definiert ist, wenn ein übergeordnetes Element eine Sammlung untergeordnetes Element unterstützt und implementiert auch ein Verhalten, bei dem die Besonderheiten des Verhaltens werden für jedes Kindelement einzeln gemeldet.

DockPanel definiert die angefügte DockPanel.Dock-Eigenschaft und DockPanel hat Code auf Klassenebene als Teil seiner Rendering-Logik (speziell MeasureOverride und ArrangeOverride). Eine DockPanel-Instanz überprüft immer, ob eines ihrer unmittelbaren untergeordneten Elemente einen Wert für DockPanel.Dock festgelegt hat. Wenn dies der Fall ist, werden diese Werte für die auf dieses bestimmte Kindelement angewendete Rendering-Logik eingegeben. Geschachtelte DockPanel-Instanzen behandeln jeweils ihre eigenen unmittelbar untergeordneten Element-Sammlungen. Dieses Verhalten ist jedoch implementierungsspezifisch, da DockPanel die DockPanel.Dock-Werte verarbeitet. Es ist theoretisch möglich, Eigenschaften anzuhängen, die Elemente beeinflussen, die über das unmittelbare Elternteil hinausgehen. Wenn das DockPanel.Die angefügte Dock-Eigenschaft wird auf ein Element gesetzt, für das kein übergeordnetes DockPanel-Element verwendet wird. Es wird kein Fehler oder eine Ausnahme ausgelöst. Dies bedeutet lediglich, dass ein globaler Eigenschaftswert festgelegt wurde, aber kein übergeordnetes DockPanel-Elternelement vorhanden ist, das die Informationen konsumieren könnte.

0

In einfachen Worten ist dies, wie ich es verstehe (bitte korrigiert mich wenn ich falsch bin).

Ein Objekt (A) implementiert eine Eigenschaft, die an ein anderes Objekt (B) angehängt wird (Objekt B weiß nicht einmal von der Existenz dieser "anfügbaren" Eigenschaft). Objekt B muss von DependencyObject erben.

Objekt A implementiert auch eine statische Methode, um die Eigenschaft "attachable" in anderen Objekten, A.GetAttachedProperty (B), zu überprüfen.

Wenn B die angefügte Eigenschaft von A hat, liest A.GetAttachedProperty und gibt den Wert zurück. Andernfalls versucht A, es zu lesen, und gibt null zurück, da es nicht da ist.