Hier ist die Erklärung für die Funktionsweise von Abhängigkeitseigenschaften, die ich mir immer gewünscht hätte, dass jemand für mich geschrieben hat. Es ist unvollständig und möglicherweise falsch, aber es wird Ihnen helfen, genug Verständnis für sie zu entwickeln, dass Sie in der Lage sein werden, die Dokumentation, die Sie lesen, zu erfassen.
Abhängigkeitseigenschaften sind eigenschaftsähnliche Werte, die über Methoden der Klasse DependencyObject
abgerufen und festgelegt werden. Sie können (und tun es auch) sehr ähnlich wie CLR-Eigenschaften aussehen, sind es aber nicht. Und das führt zu der ersten verwirrenden Sache über sie. Eine Abhängigkeitseigenschaft besteht tatsächlich aus ein paar Komponenten.
Hier ist ein Beispiel:
Document
eine Eigenschaft des RichTextBox
Objekt ist. Es ist eine echte CLR-Eigenschaft. Das heißt, es hat genau wie jede andere CLR-Eigenschaft einen Namen, einen Typ, einen Getter und einen Setter. Im Gegensatz zu "normalen" Eigenschaften erhält die Eigenschaft RichTextBox
jedoch nicht nur einen privaten Wert in der Instanz und legt diesen fest. Intern ist es wie folgt umgesetzt:
public FlowDocument Document
{
get { return (FlowDocument)GetValue(DocumentProperty); }
set { SetValue(DocumentProperty, value); }
}
Wenn Sie Document
gesetzt, der Wert, den Sie in weitergegeben SetValue
geben wird, zusammen mit DocumentProperty
. Und was ist dass? Und wie bekommt GetValue
seinen Wert? Und warum?
Zuerst das was. Es gibt eine statische Eigenschaft, die auf RichTextBox
mit dem Namen DocumentProperty
definiert ist. Wenn diese Eigenschaft deklariert ist, wird es so gemacht:
public static DependencyProperty DocumentProperty = DependencyProperty.Register(
"Document",
typeof(FlowDocument),
typeof(RichTextBox));
Die Register
Verfahren, in diesem Fall sagen die Abhängigkeitseigenschaft System, das RichTextBox
- die Art, die nicht die Instanz - jetzt eine Abhängigkeitseigenschaft hat Document
des Typs mit dem Namen FlowDocument
. Diese Methode speichert diese Informationen ... irgendwo. Wo genau ist ein Implementierungsdetail, das vor uns verborgen ist?
Wenn der Setter für die Document
Eigenschaft ruft SetValue
, die SetValue
Methode betrachtet das DocumentProperty
Argument überprüft, dass es wirklich eine Eigenschaft, die zu RichTextBox
gehört und dass value
ist die richtige Art und speichert dann den neuen Wert ... irgendwo. Die Dokumentation für DependencyObject
ist bei diesem Implementierungsdetail geheim, weil Sie es nicht wirklich wissen müssen. In meinem mentalen Modell, wie dieses Zeug funktioniert, nehme ich an, dass es eine Eigenschaft des Typs Dictionary<DependencyProperty, object>
gibt, die für die DependencyObject
privat ist, so dass abgeleitete Klassen (wie RichTextBox
) es nicht sehen können, aber GetValue
und SetValue
können es aktualisieren. Aber wer weiß, vielleicht ist es auf Pergament von Mönchen geschrieben.
Auf jeden Fall ist dieser Wert jetzt ein sogenannter "lokaler Wert", was bedeutet, dass es sich um einen Wert handelt, der genau wie eine gewöhnliche Eigenschaft lokal für diese spezifische RichTextBox
ist.
Der Punkt alle dies:
- CLR-Code nicht wissen müssen, dass eine Eigenschaft eine Abhängigkeitseigenschaft ist. Es sieht genau wie jede andere Eigenschaft aus. Sie können Anruf
GetValue
und SetValue
zu bekommen und zu setzen, aber wenn Sie etwas mit dem Abhängigkeits-Property-System tun, müssen Sie wahrscheinlich nicht.
- Im Gegensatz zu einer normalen Eigenschaft kann etwas anderes als das Objekt, an dem es beteiligt ist, in das Abrufen und Festlegen einbezogen werden. (Sie könnten dies mit Reflektion machen, denkbar, aber Reflektion ist langsam. Dinge in Wörterbüchern zu suchen ist schnell.)
- Dieses Etwas - was das Abhängigkeits-System ist - befindet sich im Wesentlichen zwischen einem Objekt und seinen Abhängigkeitseigenschaften. Und es kann alle Arten von Dingen tun.
Welche Arten von Dingen? Nun, schauen wir uns einige Anwendungsfälle an.
Bindung. Beim Binden an eine Eigenschaft muss es sich um eine Abhängigkeitseigenschaft handeln. Dies liegt daran, dass das Objekt Binding
keine Eigenschaften für das Ziel festlegt, sondern SetValue
für das Zielobjekt aufruft.
Stile. Wenn Sie die Abhängigkeitseigenschaft eines Objekts auf einen neuen Wert setzen, teilt SetValue
dem Stilsystem mit, dass Sie dies getan haben. So funktionieren Trigger: Sie erfahren nicht, dass sich der Wert einer Eigenschaft durch Magie verändert hat, sagt das Abhängigkeitseigenschaftssystem.
Dynamische Ressourcen. Wenn Sie XAML wie Background={DynamicResource MyBackground}
schreiben, können Sie den Wert der Ressource MyBackground
ändern, und der Hintergrund des darauf referenzierenden Objekts wird aktualisiert. Das ist auch keine Magie; Die dynamische Ressource ruft SetValue
auf.
Animationen. Animationen funktionieren durch Bearbeiten von Eigenschaftswerten. Diese müssen Abhängigkeitseigenschaften sein, weil die Animation SetValue
aufruft, um an sie heranzukommen.
Benachrichtigung ändern. Wenn Sie eine Abhängigkeitseigenschaft registrieren, können Sie auch eine Funktion angeben, die SetValue
aufruft, wenn sie den Wert der Eigenschaft festlegt.
Wert Vererbung. Wenn Sie eine Abhängigkeitseigenschaft registrieren, können Sie angeben, dass sie an der Vererbung von Eigenschaftenwerten beteiligt ist. Wenn Sie GetValue
aufrufen, um den Wert der Abhängigkeitseigenschaft eines Objekts abzurufen, überprüft GetValue
, ob ein lokaler Wert vorhanden ist. Wenn dies nicht der Fall ist, durchläuft es die Kette der übergeordneten Objekte, die ihre lokalen Werte für diese Eigenschaft betrachten.
Dies ist, wie Sie das FontFamily
auf einem Window
setzen können und magisch (ich benutze dieses Wort sehr) jedes Steuerelement im Fenster verwendet die neue Schriftart. Es ist auch so, dass Sie Hunderte von Steuerelementen in einem Fenster haben können, ohne dass jede eine FontFamily
Mitgliedsvariable hat, um ihre Schriftart zu verfolgen (da sie keine lokalen Werte haben), aber Sie können die FontFamily
immer noch auf einem beliebigen Steuerelement setzen (wegen des seekrit versteckten Wörterbuchs von Werten, die jeder DependencyObject
hat).
Ah, gute Informationen, danke. Ok, wie funktioniert die Magie, die es einem Kind-Steuerelement ermöglicht, auf den DataContext des Vorfahren-Fensters zuzugreifen? Kannst du mir einen Link zu diesem Artikel geben? – Cheeso
@Cheeso: Suche nach "Wertvererbung von Eigenschaften" hier: http://msdn.microsoft.com/en-us/library/ms753391.aspx Es gibt ein bisschen auf dieser Seite ... –