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
GetValue
undSetValue
damit die Verbraucher dies nicht tun müssen.Benennen Sie die Abhängigkeitseigenschaft richtig. Das
DependencyProperty
Feld solltepublic static readonly
. Es sollte einen Namen haben, der dem Namen der CLR-Eigenschaft entspricht und mit "Property" endet, z. B.Text
undTextProperty
.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
PropertyMetadata
bereitstellen: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
Grid
Steuerelement verwendet beispielsweise die angefügten EigenschaftenGrid.Row
,Grid.Column
,Grid.RowSpan
undGrid.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
TextBox
Unterklasse verwendet werdenTextBox
. - Bereitstellung eines generischen Services oder Features für einige oder alle vorhandenen Steuerelemente, z. B.
ToolTipService
oderFocusManager
. 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
DependencyProperty
wird von einemprivate
DependencyPropertyKey
. - Der CLR-Eigenschaftssetzer ist
protected
oderprivate
anstelle 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.