wpf
Propriétés de dépendance
Recherche…
Introduction
Les propriétés de dépendance sont un type de propriété qui étend une propriété CLR. Alors qu'une propriété CLR est lue directement à partir d'un membre de votre classe, une propriété de dépendance sera résolue dynamiquement lors de l'appel de la méthode GetValue () que votre objet gagne via l'héritage de la classe DependencyObject de base.
Cette section va décomposer les propriétés de dépendance et expliquer leur utilisation à la fois conceptuellement et à travers des exemples de code.
Syntaxe
- DependencyProperty.Register (nom de la chaîne, type propertyType, type ownerType)
- DependencyProperty.Register (nom de la chaîne, type propertyType, type ownerType, PropertyMetadata typeMetadata)
- DependencyProperty.Register (nom de la chaîne, type propertyType, type ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback)
- DependencyProperty.RegisterAttached (nom de la chaîne, type propertyType, type ownerType)
- DependencyProperty.RegisterAttached (nom de la chaîne, type propertyType, type ownerType, PropertyMetadata typeMetadata)
- DependencyProperty.RegisterAttached (nom de la chaîne, type propertyType, type ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback)
- DependencyProperty.RegisterReadOnly (nom de la chaîne, type propertyType, type ownerType, PropertyMetadata typeMetadata)
- DependencyProperty.RegisterReadOnly (nom de la chaîne, type propertyType, type ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback)
- DependencyProperty.RegisterAttachedReadOnly (nom de la chaîne, type propertyType, type ownerType, PropertyMetadata typeMetadata)
- DependencyProperty.RegisterAttachedReadOnly (nom de la chaîne, type propertyType, type ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback)
Paramètres
Paramètre | Détails |
---|---|
prénom | La représentation sous forme de String du nom de la propriété |
Type de propriété | Le Type de la propriété, par exemple typeof(int) |
propriétaireType | Type de la classe dans laquelle la propriété est définie, par exemple typeof(MyControl) ou typeof(MyAttachedProperties) . |
typeMetadata | Instance de System.Windows.PropertyMetadata (ou de l'une de ses sous-classes) qui définit les valeurs par défaut, les callbacks de propriété modifiés, FrameworkPropertyMetadata permet de définir des options de liaison telles que System.Windows.Data.BindingMode.TwoWay . |
ValiderValueCallback | Rappel personnalisé qui renvoie true si la nouvelle valeur de la propriété est valide, sinon fausse. |
Propriétés de dépendance standard
Quand utiliser
Pratiquement tous les contrôles WPF font un usage intensif des propriétés de dépendance. Une propriété de dépendance permet d'utiliser de nombreuses fonctionnalités WPF qui ne sont pas possibles avec les propriétés CLR standard uniquement, notamment la prise en charge des styles, des animations, de la liaison de données, de l'héritage des valeurs et des notifications de modification.
La propriété TextBox.Text
est un exemple simple de la nécessité d'une propriété de dépendance standard. Ici, la liaison de données ne serait pas possible si Text
était une propriété CLR standard.
<TextBox Text="{Binding FirstName}" />
Comment définir
Les propriétés de dépendance ne peuvent être définies que dans des classes dérivées de DependencyObject
, telles que FrameworkElement
, Control
, etc.
L'un des moyens les plus rapides de créer une propriété de dépendance standard sans avoir à retenir la syntaxe consiste à utiliser l'extrait de code "propdp" en tapant propdp
, puis en appuyant sur Tab . Un extrait de code sera inséré et pourra être modifié pour répondre à vos besoins:
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));
}
Vous devez naviguer à travers les différentes parties de l'extrait de code pour effectuer les modifications nécessaires, y compris la mise à jour du nom de la propriété, type de propriété, contenant un type de classe, et la valeur par défaut.
Conventions importantes
Il existe quelques conventions / règles importantes à suivre ici:
Créez une propriété CLR pour la propriété de dépendance. Cette propriété est utilisée dans le code-derrière de votre objet ou par d'autres consommateurs. Il devrait invoquer
GetValue
etSetValue
pour que les consommateurs n'aient pas à le faire.Nommez correctement la propriété de dépendance. Le champ
DependencyProperty
doit êtrepublic static readonly
. Il doit avoir un nom qui correspond au nom de la propriété CLR et se terminer par "Property", par exempleText
etTextProperty
.N'ajoutez pas de logique supplémentaire au setter de la propriété CLR. Le système de propriété de dépendance (et spécifiquement XAML) n'utilise pas la propriété CLR. Si vous souhaitez effectuer une action lorsque la valeur de la propriété change, vous devez fournir un rappel via
PropertyMetadata
: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. }
Mode de liaison
Pour éliminer la nécessité de spécifier Mode=TwoWay
dans les liaisons (similaire au comportement de TextBox.Text
), mettez à jour le code pour utiliser FrameworkPropertyMetadata
au lieu de PropertyMetadata
et spécifiez l'indicateur approprié:
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register("MyProperty", typeof(int), typeof(MyControl),
new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
Propriétés de dépendance attachées
Quand utiliser
Une propriété attachée est une propriété de dépendance qui peut être appliquée à n'importe quel DependencyObject
pour améliorer le comportement de divers contrôles ou services qui connaissent l'existence de la propriété.
Certains cas d'utilisation pour les propriétés jointes incluent:
- Avoir un élément parent itérer à travers ses enfants et agir sur les enfants d'une certaine manière. Par exemple, le contrôle
Grid
utilise lesGrid.Row
Grid.Column
Grid.Row
,Grid.Column
,Grid.RowSpan
etGrid.ColumnSpan
pour organiser les éléments en lignes et en colonnes. - Ajouter des éléments visuels aux contrôles existants à l'aide de modèles personnalisés, par exemple en ajoutant des filigranes à des zones de texte vides dans toute l'application sans avoir à sous-
TextBox
. - Fournir un service ou une fonctionnalité générique à certains ou à tous les contrôles existants, par exemple
ToolTipService
ouFocusManager
. Ceux-ci sont communément appelés comportements attachés . - Lorsque l'héritage de l'arborescence visuelle est requis, par exemple, similaire au comportement de
DataContext
.
Cela démontre davantage ce qui se passe dans le cas d'utilisation de la Grid
:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="Your Name:" />
<TextBox Grid.Column="1" Text="{Binding FirstName}" />
</Grid>
Grid.Column
n'est pas une propriété existant sur Label
ou TextBox
. Le contrôle Grid
examine plutôt ses éléments enfants et les organise en fonction des valeurs des propriétés attachées.
Comment définir
Nous continuerons à utiliser la Grid
pour cet exemple. La définition de Grid.Column
est indiquée ci-dessous, mais DependencyPropertyChangedEventHandler
est exclu pour des raisons de concision.
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));
}
Les propriétés attachées pouvant être associées à une grande variété d'éléments, elles ne peuvent pas être implémentées en tant que propriétés CLR. Une paire de méthodes statiques est introduite à la place.
Par conséquent, contrairement aux propriétés de dépendance standard, les propriétés attachées peuvent également être définies dans des classes non dérivées de DependencyObject
.
Les mêmes conventions de dénomination qui s'appliquent aux propriétés de dépendance normales s'appliquent également ici: la propriété de dépendance RowProperty
a les méthodes correspondantes GetRow
et SetRow
.
Mises en garde
Comme documenté sur MSDN :
Bien que l'héritage des valeurs de propriété puisse sembler fonctionner pour les propriétés de dépendance non attachées, le comportement d'héritage pour une propriété non attachée via certaines limites d'éléments dans l'arborescence d'exécution n'est pas défini. Utilisez toujours RegisterAttached pour enregistrer les propriétés dans lesquelles vous spécifiez Inherits dans les métadonnées.
Propriétés de dépendance en lecture seule
Quand utiliser
Une propriété de dépendance en lecture seule est similaire à une propriété de dépendance normale, mais elle est structurée pour ne pas permettre que sa valeur soit définie en dehors du contrôle. Cela fonctionne bien si vous avez une propriété purement informative pour les consommateurs, par exemple IsMouseOver
ou IsKeyboardFocusWithin
.
Comment définir
Tout comme les propriétés de dépendance standard, une propriété de dépendance en lecture seule doit être définie sur une classe dérivée de 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); }
}
}
Les mêmes conventions qui s'appliquent aux propriétés de dépendance régulières s'appliquent également ici, mais avec deux différences principales:
- Le
DependencyProperty
provient d'unDependencyPropertyKey
private
. - Le setter de propriétés CLR est
protected
ouprivate
au lieu depublic
.
Notez que le poseur passe MyPropertyPropertyKey
et non MyPropertyProperty
à la SetValue
méthode. Étant donné que la propriété a été définie en lecture seule, toute tentative d'utilisation de SetValue
sur la propriété doit être utilisée avec une surcharge qui reçoit DependencyPropertyKey
; sinon, une InvalidOperationException
sera lancée.