Vue d’ensemble des propriétés de dépendance (WPF .NET)
WPF (Windows Presentation Foundation) fournit un ensemble de services qui permettent d’étendre la fonctionnalité de la propriété d’un type. Collectivement, ces services sont appelés système de propriétés WPF. Une propriété qui est sauvegardée par le système de propriétés WPF est appelée propriété de dépendance. Cette vue d’ensemble décrit le système de propriétés WPF et les fonctionnalités d’une propriété de dépendance, notamment comment utiliser les propriétés de dépendance existantes en XAML et dans le code. Elle introduit également des aspects spécialisés des propriétés de dépendance, tels que les métadonnées de propriétés de dépendance et comment créer votre propre propriété de dépendance dans une classe personnalisée.
Important
La documentation desktop Guide pour .NET 7 et .NET 6 est en cours de construction.
Prérequis
Cet article suppose une connaissance de base du système de type .NET et de la programmation orientée objet. Pour suivre les exemples de cet article, il est utile de comprendre XAML et de savoir comment écrire des applications WPF. Pour plus d’informations, consultez Tutoriel : Créer une application WPF avec .NET.
Propriétés de dépendance et propriétés CLR
Les propriétés WPF sont généralement exposées en tant que propriétés .NET standard. Vous pouvez interagir avec ces propriétés à un niveau de base et ne jamais savoir qu’elles sont implémentées en tant que propriété de dépendance. Toutefois, la connaissance de certaines ou de toutes les fonctionnalités du système de propriétés WPF vous aidera à tirer parti de ces fonctionnalités.
L’objectif des propriétés de dépendance est de fournir un moyen de calculer la valeur d’une propriété en fonction de la valeur d’autres entrées, telles que :
- Propriétés système, telles que les thèmes et les préférences de l’utilisateur.
- Mécanismes de détermination des propriétés juste-à-temps, tels que la liaison de données et les animations/storyboards.
- Modèles à usage multiple, tels que les ressources et les styles.
- Valeurs connues par le biais de relations parent-enfant avec d’autres éléments dans l’arborescence d’éléments.
En outre, une propriété de dépendance peut fournir :
- Validation autonome.
- Valeurs par défaut.
- Rappels qui surveillent les modifications apportées à d’autres propriétés.
- Système qui peut contraindre des valeurs de propriété basées sur les informations d’exécution.
Les classes dérivées peuvent modifier certaines caractéristiques d’une propriété existante en remplaçant les métadonnées d’une propriété de dépendance, au lieu de remplacer l’implémentation réelle des propriétés existantes ou de créer de nouvelles propriétés.
Dans la référence du Kit de développement logiciel (SDK), vous pouvez identifier une propriété de dépendance par la présence d’une section Informations sur les propriétés de dépendance sur la page de référence managée de cette propriété. La section Informations sur la propriété de dépendance inclut un lien vers le DependencyProperty champ d’identificateur de cette propriété de dépendance. Il inclut également la liste des options de métadonnées pour cette propriété, des informations de remplacement par classe et d’autres détails.
Les propriétés CLR reposent sur les propriétés de dépendance
Les propriétés de dépendance et le système de propriétés WPF étendent les fonctionnalités de propriété en fournissant un type qui sauvegarde une propriété, en guise d’alternative au modèle standard de sauvegarde d’une propriété avec un champ privé. Le nom de ce type est DependencyProperty. L’autre type important qui définit le système de propriétés WPF est DependencyObject, qui définit la classe de base qui peut inscrire et posséder une propriété de dépendance.
Voici quelques termes couramment utilisés :
Propriété de dépendance, qui est une propriété adossée à un DependencyProperty.
Identificateur de propriété de dépendance, qui est un
DependencyProperty
instance obtenu en tant que valeur de retour lors de l’inscription d’une propriété de dépendance, puis stocké en tant que membre statique d’une classe. La plupart des API qui interagissent avec le système de propriétés WPF utilisent l’identificateur de propriété de dépendance comme paramètre.CLR « wrapper », qui est les
get
implémentations etset
pour la propriété . Ces implémentations incorporent l’identificateur de propriété de dépendance en l’utilisant dans les GetValue appels et SetValue . De cette façon, le système de propriétés WPF fournit la sauvegarde de la propriété.
L’exemple suivant définit la IsSpinning
propriété de dépendance pour afficher la relation de l’identificateur DependencyProperty
à la propriété qu’il sauvegarde.
public static readonly DependencyProperty IsSpinningProperty = DependencyProperty.Register(
"IsSpinning", typeof(bool),
typeof(MainWindow)
);
public bool IsSpinning
{
get => (bool)GetValue(IsSpinningProperty);
set => SetValue(IsSpinningProperty, value);
}
Public Shared ReadOnly IsSpinningProperty As DependencyProperty =
DependencyProperty.Register("IsSpinning", GetType(Boolean), GetType(MainWindow))
Public Property IsSpinning As Boolean
Get
Return GetValue(IsSpinningProperty)
End Get
Set(value As Boolean)
SetValue(IsSpinningProperty, value)
End Set
End Property
La convention de nommage de la propriété et de son champ DependencyProperty de stockage est importante. Le nom du champ est toujours le nom de la propriété, auquel est ajouté le suffixe Property
. Pour plus d’informations sur cette convention et ses raisons, consultez Propriétés de dépendance personnalisées.
Définition de valeurs de propriété
Vous pouvez définir des propriétés dans le code ou en XAML.
Définition de valeurs de propriété en XAML
L’exemple XAML suivant définit la couleur d’arrière-plan d’un bouton sur rouge. La valeur de chaîne de l’attribut XAML est convertie en type par l’analyseur XAML WPF en type WPF. Dans le code généré, le type WPF est un Color, par le biais d’un SolidColorBrush.
<Button Content="I am red" Background="Red"/>
XAML prend en charge plusieurs formes syntaxiques pour définir des propriétés. La syntaxe à utiliser pour une propriété particulière dépend du type valeur utilisé par une propriété et d’autres facteurs, tels que la présence d’un convertisseur de type. Pour plus d’informations sur la syntaxe XAML pour la définition des propriétés, consultez XAML dans WPF et Syntaxe XAML En détail.
L’exemple XAML suivant montre un autre arrière-plan de bouton qui utilise la syntaxe d’élément de propriété au lieu de la syntaxe d’attribut. Au lieu de définir une couleur unie simple, le code XAML définit la propriété button Background
sur une image. Un élément représente cette image, et un attribut de l’élément imbriqué spécifie la source de l’image.
<Button Content="I have an image background">
<Button.Background>
<ImageBrush ImageSource="stripes.jpg"/>
</Button.Background>
</Button>
Définition de propriétés dans le code
La définition des valeurs de propriétés de dépendance dans le code est généralement simplement un appel à l’implémentation set
exposée par le « wrapper » du CLR :
Button myButton = new();
myButton.Width = 200.0;
Dim myButton As New Button With {
.Width = 200.0
}
L’obtention d’une valeur de propriété est essentiellement un appel à l’implémentation get
« wrapper » :
double whatWidth = myButton.Width;
Dim whatWidth As Double = myButton.Width
Vous pouvez également appeler les API système de GetValue propriété et SetValue directement. L’appel direct des API est approprié pour certains scénarios, mais généralement pas lorsque vous utilisez des propriétés existantes. En règle générale, les wrappers sont plus pratiques et offrent une meilleure exposition de la propriété pour les outils de développement.
Vous pouvez aussi définir les propriétés en XAML et y accéder ultérieurement dans le code, par l’intermédiaire du code-behind. Pour plus d’informations, consultez Code-behind et XAML dans WPF.
Fonctionnalité de propriété fournie par une propriété de dépendance
Contrairement à une propriété qui est adossée à un champ, une propriété de dépendance étend les fonctionnalités d’une propriété. Souvent, la fonctionnalité ajoutée représente ou prend en charge l’une de ces fonctionnalités :
Ressources
Vous pouvez définir une valeur de propriété de dépendance en référençant une ressource. Les ressources sont généralement spécifiées en tant que Resources
valeur de propriété d’un élément racine de page ou de l’application, car ces emplacements offrent un accès pratique à la ressource. Dans cet exemple, nous définissons une SolidColorBrush ressource :
<StackPanel.Resources>
<SolidColorBrush x:Key="MyBrush" Color="Gold"/>
</StackPanel.Resources>
Maintenant que la ressource est définie, nous pouvons référencer la ressource pour fournir une valeur pour la Background
propriété :
<Button Background="{DynamicResource MyBrush}" Content="I am gold" />
En XAML WPF, vous pouvez utiliser une référence de ressource statique ou dynamique. Cette ressource particulière est référencée en tant que DynamicResource. Une référence de ressource dynamique ne peut être utilisée que pour définir une propriété de dépendance. Il s’agit donc spécifiquement de l’utilisation de la référence de ressource dynamique activée par le système de propriétés WPF. Pour plus d’informations, consultez Ressources XAML.
Notes
Les ressources sont traitées comme une valeur locale, ce qui signifie que si vous définissez une autre valeur locale, vous éliminerez la référence de ressource. Pour plus d’informations, consultez Priorité des valeurs de propriété de dépendance.
Liaison de données
Une propriété de dépendance peut référencer une valeur par l’intermédiaire d’une liaison de données. La liaison de données fonctionne via une syntaxe d’extension de balisage spécifique en XAML, ou via l’objet Binding dans du code. Avec la liaison de données, la détermination de la valeur de propriété finale est différée jusqu’au moment de l’exécution, date à laquelle la valeur est obtenue à partir d’une source de données.
L’exemple suivant définit la Content propriété pour un Button, à l’aide d’une liaison déclarée en XAML. La liaison utilise un contexte de données hérité et une source de données XmlDataProvider (non illustrée). La liaison elle-même spécifie la propriété source dans la source de données par XPath.
<Button Content="{Binding Source={StaticResource TestData}, XPath=test[1]/@text}"/>
Notes
Les liaisons sont traitées comme une valeur locale, ce qui signifie que si vous définissez une autre valeur locale, vous éliminerez la liaison. Pour plus d’informations, consultez Priorité des valeurs de propriété de dépendance.
Les propriétés de dépendance, ou la DependencyObject classe, ne prennent pas en charge INotifyPropertyChanged en mode natif la notification des modifications apportées à DependencyObject
la valeur de propriété source pour les opérations de liaison de données. Pour plus d’informations sur la création de propriétés à utiliser dans la liaison de données qui peuvent signaler des modifications apportées à une cible de liaison de données, consultez Vue d’ensemble de la liaison de données.
Styles
Les styles et les modèles sont des raisons convaincantes d’utiliser des propriétés de dépendance. Les styles sont particulièrement utiles pour définir les propriétés qui définissent l’interface utilisateur de l’application. Ils sont généralement définis en tant que ressources en XAML. Les styles interagissent avec le système de propriétés, car ils contiennent généralement des « setters » pour des propriétés particulières et des « déclencheurs » qui modifient une valeur de propriété en fonction de la valeur d’exécution d’une autre propriété.
L’exemple suivant crée un style simple, qui serait défini à l’intérieur d’un Resources dictionnaire (non affiché). Ensuite, ce style est appliqué directement à la Style propriété d’un Button. La méthode setter contenue dans le style définit la propriété Background pour un Button
mis en vert.
<Style x:Key="GreenButtonStyle">
<Setter Property="Control.Background" Value="Green"/>
</Style>
<Button Style="{StaticResource GreenButtonStyle}" Content="I am green"/>
Pour plus d’informations, consultez Style et création de modèles.
Animations
Les propriétés de dépendance peuvent être animées. Lorsqu’une animation appliquée s’exécute, la valeur animée a une priorité supérieure à toute autre valeur de propriété, y compris une valeur locale.
L’exemple suivant anime la Background propriété d’un Button. Techniquement, la syntaxe de l’élément de propriété définit un vide SolidColorBrush comme Background
, et la Color propriété de est SolidColorBrush
animée.
<Button Content="I am animated">
<Button.Background>
<SolidColorBrush x:Name="AnimBrush"/>
</Button.Background>
<Button.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetName="AnimBrush"
Storyboard.TargetProperty="(SolidColorBrush.Color)"
From="Blue" To="White" Duration="0:0:1"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
Pour plus d’informations sur l’animation des propriétés, consultez Vue d’ensemble desanimations et Vue d’ensemble des storyboards.
Substitutions de métadonnées
Vous pouvez modifier les comportements spécifiques d’une propriété de dépendance en remplaçant ses métadonnées lorsque vous dérivez de la classe qui a initialement inscrit la propriété de dépendance. La substitution de métadonnées s’appuie sur l’identificateur DependencyProperty et ne nécessite pas de ré-implémentation de la propriété. La modification des métadonnées est gérée en mode natif par le système de propriétés. Chaque classe contient potentiellement des métadonnées individuelles pour toutes les propriétés héritées des classes de base, sur une base par type.
L’exemple suivant remplace les métadonnées d’une DefaultStyleKey propriété de dépendance. La substitution des métadonnées pour cette propriété de dépendance particulière fait partie d’un modèle d’implémentation permettant de créer des contrôles qui peuvent utiliser des styles par défaut à partir de thèmes.
public class SpinnerControl : ItemsControl
{
static SpinnerControl() => DefaultStyleKeyProperty.OverrideMetadata(
typeof(SpinnerControl),
new FrameworkPropertyMetadata(typeof(SpinnerControl))
);
}
Public Class SpinnerControl
Inherits ItemsControl
Shared Sub New()
DefaultStyleKeyProperty.OverrideMetadata(GetType(SpinnerControl), New FrameworkPropertyMetadata(GetType(SpinnerControl)))
End Sub
End Class
Pour plus d’informations sur la substitution ou l’accès aux métadonnées pour les propriétés de dépendance, consultez Remplacer les métadonnées pour une propriété de dépendance.
Héritage d’une valeur de propriété
Un élément peut hériter de la valeur d’une propriété de dépendance de son parent dans l’arborescence d’objets.
Notes
Le comportement d’héritage des valeurs de propriété n’est pas globalement activé pour toutes les propriétés de dépendance, car le temps de calcul de l’héritage affecte les performances. L’héritage de la valeur de propriété est généralement activé uniquement dans les scénarios qui suggèrent l’applicabilité. Vous pouvez case activée si une propriété de dépendance hérite en examinant la section Informations sur la propriété de dépendance pour cette propriété de dépendance dans la référence du SDK.
L’exemple suivant montre une liaison qui inclut la DataContext propriété permettant de spécifier la source de la liaison. Par conséquent, les liaisons dans les objets enfants n’ont pas besoin de spécifier la source et peuvent utiliser la valeur héritée de dans DataContext
l’objet parent StackPanel . Ou bien, un objet enfant peut spécifier directement son propre DataContext
ou un Source dans , Bindinget ne pas utiliser la valeur héritée.
<StackPanel Canvas.Top="50" DataContext="{Binding Source={StaticResource TestData}}">
<Button Content="{Binding XPath=test[2]/@text}"/>
</StackPanel>
Pour plus d’informations, consultez Héritage de la valeur de propriété.
Intégration du concepteur WPF
Les contrôles personnalisés avec des propriétés implémentées en tant que propriétés de dépendance s’intègrent bien à WPF Designer pour Visual Studio. Par exemple, la possibilité de modifier les propriétés de dépendance directes et jointes dans la fenêtre Propriétés . Pour plus d’informations, consultez Vue d’ensemble de la création de contrôles.
Priorité de la valeur d’une propriété de dépendance
Toutes les entrées basées sur des propriétés dans le système de propriétés WPF peuvent définir la valeur d’une propriété de dépendance. Il existe une priorité de valeur de propriété de dépendance afin que les différents scénarios permettant d’obtenir leurs valeurs interagissent de manière prévisible.
Notes
La documentation du KIT de développement logiciel (SDK) utilise parfois le terme « valeur locale » ou « valeur définie localement » lors de la discussion des propriétés de dépendance. Une valeur définie localement est une valeur de propriété définie directement sur un objet instance dans le code ou en tant qu’attribut d’élément en XAML.
L’exemple suivant inclut un style qui s’applique à la Background propriété d’un bouton, mais spécifie un bouton avec une propriété définie Background
localement. Techniquement, ce bouton a sa Background
propriété définie deux fois, bien qu’une seule valeur s’applique, la valeur avec la priorité la plus élevée. Une valeur définie localement a la priorité la plus élevée, à l’exception d’une animation en cours d’exécution, qui n’existe pas ici. Par conséquent, le deuxième bouton utilise la valeur définie localement pour la Background
propriété, au lieu de la valeur de setter de style. Le premier bouton n’a pas de valeur locale ou d’autre valeur ayant une priorité supérieure à celle d’un setter de style, et utilise donc la valeur de setter de style pour la Background
propriété.
<StackPanel>
<StackPanel.Resources>
<Style x:Key="{x:Type Button}" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Orange"/>
</Style>
</StackPanel.Resources>
<Button>I am styled orange</Button>
<Button Background="Pink">I am locally set to pink (not styled orange)</Button>
</StackPanel>
Pourquoi la priorité des propriétés de dépendance existe-t-elle ?
Les valeurs définies localement sont prioritaires sur les valeurs de setter de style, ce qui prend en charge le contrôle local des propriétés des éléments. Pour plus d’informations, consultez Priorité de la valeur de propriété de dépendance.
Notes
Un certain nombre de propriétés définies sur les éléments WPF ne sont pas des propriétés de dépendance, car les propriétés de dépendance ont généralement été implémentées uniquement lorsqu’une fonctionnalité du système de propriétés WPF était requise. Les fonctionnalités incluent la liaison de données, le style, l’animation, la prise en charge des valeurs par défaut, l’héritage, les propriétés jointes et l’invalidation.
En savoir plus sur les propriétés de dépendance
Les développeurs de composants ou les développeurs d’applications peuvent souhaiter créer leur propre propriété de dépendance pour ajouter des fonctionnalités, telles que la prise en charge de la liaison de données ou des styles, ou la prise en charge de l’invalidation et de la contrainte de valeur. Pour plus d’informations, consultez Propriétés de dépendance personnalisées.
Considérez les propriétés de dépendance comme des propriétés publiques, accessibles ou détectables par tout appelant ayant accès à un instance. Pour plus d’informations, consultez Sécurité des propriétés de dépendance.
Une propriété jointe est un type de propriété qui prend en charge une syntaxe spécialisée en XAML. Une propriété jointe n’a souvent pas de correspondance 1:1 avec une propriété Common Language Runtime et n’est pas nécessairement une propriété de dépendance. L’objectif main d’une propriété jointe est d’autoriser les éléments enfants à signaler des valeurs de propriété à un élément parent, même si l’élément parent et l’élément enfant n’incluent pas cette propriété dans les listes des membres de la classe. L’un des scénarios principaux consiste à permettre à un élément enfant d’indiquer aux éléments parents comment les présenter dans l’interface utilisateur. Pour obtenir des exemples, consultez Dock et Left. Pour plus d’informations, consultez Vue d’ensemble des propriétés jointes.