wpf
Abhängigkeitseigenschaften
Suche…
Einführung
Abhängigkeitseigenschaften sind ein Eigenschaftstyp, der eine CLR-Eigenschaft erweitert. Während eine CLR-Eigenschaft direkt von einem Member Ihrer Klasse gelesen wird, wird eine Dependency-Eigenschaft beim Aufrufen der GetValue () - Methode, die Ihr Objekt durch Vererbung von der Basisklasse DependencyObject erhält, dynamisch aufgelöst.
In diesem Abschnitt werden die Abhängigkeitseigenschaften aufgeschlüsselt und deren Verwendung sowohl konzeptionell als auch anhand von Codebeispielen erläutert.
Syntax
- DependencyProperty.Register (Zeichenfolgenname, Typ propertyType, Type ownerType)
- DependencyProperty.Register (Zeichenfolgenname, Typ propertyType, Type ownerType, PropertyMetadata typeMetadata)
- DependencyProperty.Register (Zeichenfolgenname, Typ propertyType, Type ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback)
- DependencyProperty.RegisterAttached (Zeichenfolgenname, Typ propertyType, Type ownerType)
- DependencyProperty.RegisterAttached (Zeichenfolgenname, Typ propertyType, Type ownerType, PropertyMetadata typeMetadata)
- DependencyProperty.RegisterAttached (Stringname, Typ propertyType, Type ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback)
- DependencyProperty.RegisterReadOnly (Name der Zeichenfolge, Typ propertyType, Type ownerType, PropertyMetadata typeMetadata)
- DependencyProperty.RegisterReadOnly (Zeichenfolgenname, Typ propertyType, Type ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback)
- DependencyProperty.RegisterAttachedReadOnly (Zeichenfolgenname, Typ propertyType, Type ownerType, PropertyMetadata typeMetadata)
- DependencyProperty.RegisterAttachedReadOnly (Zeichenfolgenname, Typ propertyType, Type ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback)
Parameter
| Parameter | Einzelheiten |
|---|---|
| Name | Die String Darstellung des Namens der Eigenschaft |
| Art der Immobilie | Der Type der Eigenschaft, zB typeof(int) |
| ownerType | Der Type der Klasse, in der die Eigenschaft definiert wird, z. B. typeof(MyControl) oder typeof(MyAttachedProperties) . |
| typeMetadata | Instanz von System.Windows.PropertyMetadata (oder einer ihrer Unterklassen), die Standardwerte definiert, die Eigenschaft geänderter Callbacks. Mit FrameworkPropertyMetadata können Bindungsoptionen wie System.Windows.Data.BindingMode.TwoWay . |
| validateValueCallback | Benutzerdefinierter Rückruf, der true zurückgibt, wenn der neue Wert der Eigenschaft gültig ist, andernfalls false. |
Standardabhängigkeitseigenschaften
Wann verwenden?
Praktisch alle WPF-Steuerelemente nutzen die Abhängigkeitseigenschaften stark. Eine Abhängigkeitseigenschaft ermöglicht die Verwendung vieler WPF-Funktionen, die mit den Standard-CLR-Eigenschaften allein nicht möglich sind, einschließlich der Unterstützung für Stile, Animationen, Datenbindung, Wertvererbung und Änderungsbenachrichtigungen.
Die TextBox.Text Eigenschaft ist ein einfaches Beispiel dafür, wo eine Standardabhängigkeitseigenschaft benötigt wird. Hier wäre eine Datenbindung nicht möglich, wenn Text eine CLR-Standardeigenschaft war.
<TextBox Text="{Binding FirstName}" />
Wie zu definieren
Abhängigkeitseigenschaften können nur in von DependencyObject abgeleiteten Klassen wie FrameworkElement , Control usw. definiert werden.
Eine der schnellsten Methoden zum Erstellen einer Standardabhängigkeitseigenschaft, ohne sich an die Syntax zu erinnern, besteht darin, den "propdp" -Schnipsel zu verwenden, indem Sie propdp und dann die Tabulatortaste drücken. Ein Code-Snippet wird eingefügt, der dann an Ihre Bedürfnisse angepasst werden kann:
public class MyControl : Control
{
public int MyProperty
{
get { return (int)GetValue(MyPropertyProperty); }
set { SetValue(MyPropertyProperty, value); }
}
// Using a DependencyProperty as the backing store for MyProperty.
// This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register("MyProperty", typeof(int), typeof(MyControl),
new PropertyMetadata(0));
}
Sie sollten Tab durch die verschiedenen Teile des Code - Schnipsel , die notwendigen Änderungen vorzunehmen, einschließlich den Namen der Eigenschaft zu aktualisieren, Objekttyp, Klassentyp enthält, und den Standardwert.
Wichtige Konventionen
Hier sind einige wichtige Konventionen / Regeln zu beachten:
Erstellen Sie eine CLR-Eigenschaft für die Abhängigkeitseigenschaft. Diese Eigenschaft wird im Code-Behind Ihres Objekts oder von anderen Konsumenten verwendet. Es sollte
GetValueundSetValuedamit die Verbraucher dies nicht tun müssen.Benennen Sie die Abhängigkeitseigenschaft richtig. Das
DependencyPropertyFeld solltepublic static readonly. Es sollte einen Namen haben, der dem Namen der CLR-Eigenschaft entspricht und mit "Property" endet, z. B.TextundTextProperty.Fügen Sie dem Einsteller der CLR-Eigenschaft keine zusätzliche Logik hinzu. Das Abhängigkeitseigenschaftssystem (und insbesondere XAML) verwendet die CLR-Eigenschaft nicht. Wenn Sie eine Aktion ausführen möchten, wenn sich der Wert der Eigenschaft ändert, müssen Sie einen Rückruf über
PropertyMetadatabereitstellen:public static readonly DependencyProperty MyPropertyProperty = DependencyProperty.Register("MyProperty", typeof(int), typeof(MyControl), new PropertyMetadata(0, MyPropertyChangedHandler)); private static void MyPropertyChangedHandler(DependencyObject sender, DependencyPropertyChangedEventArgs args) { // Use args.OldValue and args.NewValue here as needed. // sender is the object whose property changed. // Some unboxing required. }
Bindungsmodus
Um die Notwendigkeit der Angabe von Mode=TwoWay in Bindungen (ähnlich dem Verhalten von TextBox.Text ) zu TextBox.Text aktualisieren Sie den Code, um FrameworkPropertyMetadata anstelle von PropertyMetadata und geben Sie das entsprechende Flag an:
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register("MyProperty", typeof(int), typeof(MyControl),
new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
Angehängte Abhängigkeitseigenschaften
Wann verwenden?
Eine angefügte Eigenschaft ist eine Abhängigkeitseigenschaft, die auf jedes DependencyObject angewendet werden kann, um das Verhalten verschiedener Steuerelemente oder Dienste zu verbessern, die sich der Existenz der Eigenschaft bewusst sind.
Einige Anwendungsfälle für angefügte Eigenschaften umfassen:
- Ein Elternelement iteriert durch seine Kinder und wirkt auf eine bestimmte Weise auf die Kinder ein. Das
GridSteuerelement verwendet beispielsweise die angefügten EigenschaftenGrid.Row,Grid.Column,Grid.RowSpanundGrid.ColumnSpan, um Elemente in Zeilen und Spalten anzuordnen. - Hinzufügen von Visuals zu vorhandenen Steuerelementen mit benutzerdefinierten Vorlagen, z. B. Hinzufügen von Wasserzeichen zu leeren Textfeldern, ohne dass
TextBoxUnterklasse verwendet werdenTextBox. - Bereitstellung eines generischen Services oder Features für einige oder alle vorhandenen Steuerelemente, z. B.
ToolTipServiceoderFocusManager. Diese werden im Allgemeinen als angefügte Verhaltensweisen bezeichnet . - Wenn die Vererbung nach unten erfolgt, ist der visuelle Baum erforderlich, z. B. ähnlich dem Verhalten von
DataContext.
Dies zeigt weiter, was im Grid Anwendungsfall passiert:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="Your Name:" />
<TextBox Grid.Column="1" Text="{Binding FirstName}" />
</Grid>
Grid.Column ist keine Eigenschaft, die in Label oder TextBox . Das Grid Steuerelement durchsucht die untergeordneten Elemente und ordnet sie gemäß den Werten der angefügten Eigenschaften an.
Wie zu definieren
Wir werden Grid für dieses Beispiel verwenden. Die Definition von Grid.Column wird unten gezeigt, der DependencyPropertyChangedEventHandler ist jedoch der Kürze Grid.Column ausgeschlossen.
public static readonly DependencyProperty RowProperty =
DependencyProperty.RegisterAttached("Row", typeof(int), typeof(Grid),
new FrameworkPropertyMetadata(0, ...));
public static void SetRow(UIElement element, int value)
{
if (element == null)
throw new ArgumentNullException("element");
element.SetValue(RowProperty, value);
}
public static int GetRow(UIElement element)
{
if (element == null)
throw new ArgumentNullException("element");
return ((int)element.GetValue(RowProperty));
}
Da die angefügten Eigenschaften an eine Vielzahl von Elementen angehängt werden können, können sie nicht als CLR-Eigenschaften implementiert werden. Stattdessen wird ein Paar statischer Methoden eingeführt.
Im Gegensatz zu Standardabhängigkeitseigenschaften können angefügte Eigenschaften auch in Klassen definiert werden, die nicht von DependencyObject abgeleitet sind.
Die gleichen Namenskonventionen gelten auch für reguläre Abhängigkeitseigenschaften: Die Abhängigkeitseigenschaft RowProperty verfügt über die entsprechenden Methoden GetRow und SetRow .
Vorsichtsmaßnahmen
Wie auf MSDN dokumentiert :
Obwohl die Vererbung von Eigenschaftswerten für nicht angefügte Abhängigkeitseigenschaften zu funktionieren scheint, ist das Vererbungsverhalten für eine nicht angefügte Eigenschaft über bestimmte Elementgrenzen in der Laufzeitstruktur nicht definiert. Verwenden Sie immer RegisterAttached, um Eigenschaften zu registrieren, in denen Sie Inherits in den Metadaten angeben.
Schreibgeschützte Abhängigkeitseigenschaften
Wann verwenden?
Eine schreibgeschützte Abhängigkeitseigenschaft ähnelt einer normalen Abhängigkeitseigenschaft. Sie ist jedoch so strukturiert, dass ihr Wert nicht außerhalb des Steuerelements festgelegt werden kann. Dies funktioniert gut, wenn Sie über eine Eigenschaft verfügen, die rein informativ für Verbraucher ist, z. B. IsMouseOver oder IsKeyboardFocusWithin .
Wie zu definieren
Genau wie Standardabhängigkeitseigenschaften muss eine schreibgeschützte Abhängigkeitseigenschaft für eine Klasse definiert werden, die von DependencyObject .
public class MyControl : Control
{
private static readonly DependencyPropertyKey MyPropertyPropertyKey =
DependencyProperty.RegisterReadOnly("MyProperty", typeof(int), typeof(MyControl),
new FrameworkPropertyMetadata(0));
public static readonly DependencyProperty MyPropertyProperty = MyPropertyPropertyKey.DependencyProperty;
public int MyProperty
{
get { return (int)GetValue(MyPropertyProperty); }
private set { SetValue(MyPropertyPropertyKey, value); }
}
}
Die gleichen Konventionen, die für reguläre Abhängigkeitseigenschaften gelten, gelten auch hier, jedoch mit zwei Hauptunterschieden:
- Die
DependencyPropertywird von einemprivateDependencyPropertyKey. - Der CLR-Eigenschaftssetzer ist
protectedoderprivateanstelle vonpublic.
Beachten Sie, dass der Setter MyPropertyPropertyKey und nicht MyPropertyProperty an die SetValue Methode SetValue . Da die Eigenschaft als schreibgeschützt definiert wurde, muss jeder Versuch, SetValue für die Eigenschaft zu verwenden, mit Überladung verwendet werden, die DependencyPropertyKey empfängt. Andernfalls wird eine InvalidOperationException ausgelöst.