Pour afficher l’article en anglais, activez la case d’option Anglais. Vous pouvez aussi afficher la version anglaise dans une fenêtre contextuelle en faisant glisser le pointeur de la souris sur le texte.
Traduction
Anglais

Vue d'ensemble des propriétés de dépendance

 

Publication: juin 2016

Windows Presentation Foundation (WPF) fournit un jeu des services qui peuvent être utilisés pour étendre les fonctionnalités d'une propriété Common Language Runtime (CLR). Ensemble, ces services sont en général connus sous le nom de système de propriétés WPF. Une propriété stocké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. Elle s'intéresse notamment à l'utilisation des propriétés de dépendance existantes en XAML et dans le code. Cette vue d'ensemble introduit également des aspects spécialisés des propriétés de dépendance, comme les métadonnées de propriété de dépendance, et explique comment créer votre propre propriété de dépendance dans une classe personnalisée.

Cette rubrique suppose que vous disposez de quelques connaissances de base de CLR et de la programmation orientée objet. Pour pouvoir suivre les exemples dans cette rubrique, vous devez également maîtriser le XAML et savoir écrire des applications WPF. Pour plus d'informations, consultez Procédure pas à pas : mise en route de WPF.

Dans WPF, les propriétés sont généralement exposées comme propriétés Common Language Runtime (CLR). À un niveau basique, vous pouvez interagir directement avec ces propriétés sans jamais savoir qu'elles sont implémentées en tant que propriété de dépendance. Toutefois, vous devez vous familiariser avec quelques-unes ou toutes les fonctionnalités du système de propriétés WPF pour pouvoir en tirer parti.

Les propriétés de dépendance ont pour but de permettre de calculer la valeur d'une propriété en fonction de la valeur d'autres entrées. Ces autres entrées peuvent correspondre à des propriétés système (p. ex. des thèmes et des préférences utilisateur), des mécanismes de détermination de la propriété juste-à-temps (p. ex. la liaison de données et les animations/tables de montage séquentiel), des modèles à utilisation multiple (comme les ressources et les styles) ou des valeurs connues à travers des relations parent-enfant avec d'autres éléments dans l'arborescence d'éléments. De plus, une propriété de dépendance peut être implémentée pour fournir une validation autonome, des valeurs par défaut, des rappels que le moniteur remplace par d'autres propriétés, ainsi qu'un système qui peut forcer des valeurs de propriété selon des informations d'exécution potentielles. Les classes dérivées peuvent également modifier certaines caractéristiques spécifiques d'une propriété existante en substituant les métadonnées de propriété de dépendance, au lieu de remplacer l'implémentation réelle de propriétés existantes ou de créer de nouvelles propriétés.

Dans la référence du Kit de développement, vous pouvez identifier les propriétés de dépendance par la présence de la section Informations sur les propriétés de dépendance à la page des références gérées de cette propriété. La section Informations sur les propriétés de dépendance inclut un lien vers le champ d'identificateur DependencyProperty pour cette propriété de dépendance, ainsi qu'une liste des options de métadonnées définies pour cette propriété, des informations de substitution par classe et d'autres détails.

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 stocke une propriété, comme une implémentation alternative du modèle standard de stockage de la propriété avec un champ privé. Ce type s'appelle DependencyProperty. L'autre type important qui définit le système de propriétés WPF s'appelle DependencyObject.DependencyObject définit la classe de base qui peut enregistrer et posséder une propriété de dépendance.

Ci-dessous figure un résumé de la terminologie utilisée dans cette documentation software development kit (SDK) pour traiter des propriétés de dépendance :

  • Propriété de dépendance : Propriété stockée par une DependencyProperty.

  • Identificateur de propriété de dépendance : instance DependencyProperty, obtenue comme valeur de retour lors de l'enregistrement d'une propriété de dépendance, puis stockée comme membre statique d'une classe. Cet identificateur est utilisé comme paramètre pour de nombreuses APIs qui interagissent avec le système de propriétés WPF.

  • "Wrapper CLR : Implémentations Get et Set réelles pour la propriété. Ces implémentations incorporent l'identificateur de propriété de dépendance en l'utilisant dans les appels GetValue et SetValue, stockant ainsi la propriété à l'aide du système de propriétés WPF.

L'exemple suivant définit la propriété de dépendanceIsSpinning et montre la relation de l'identificateur DependencyProperty avec la propriété qu'il stocke.

public static readonly DependencyProperty IsSpinningProperty = 
    DependencyProperty.Register(
    "IsSpinning", typeof(Boolean),
    );
public bool IsSpinning
{
    get { return (bool)GetValue(IsSpinningProperty); }
    set { SetValue(IsSpinningProperty, value); }
}

La convention d'affectation de noms de la propriété et son champ de stockage DependencyProperty est importante. Le nom du champ correspond toujours au nom de la propriété, avec le suffixe Property. Pour plus d'informations sur cette convention et ses raisons, consultez Propriétés de dépendance personnalisées.

Vous pouvez définir des propriétés dans le code ou en XAML.

L'exemple XAML suivant affecte la couleur rouge à l'arrière-plan d'un bouton. Cet exemple illustre un cas dans lequel la valeur de la chaîne simple d'un attribut XAML est convertie par type par l'analyseur XAML WPF en un type WPF (Color, par l'intermédiaire de SolidColorBrush) dans le code généré.

<Button Background="Red" Content="Button!"/>

XAML prend en charge diverses formes de syntaxe pour définir des propriétés. La syntaxe à utiliser pour une propriété dépendra du type valeur utilisé par la propriété ainsi que 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 de propriétés, consultez Vue d'ensemble du langage XAML (WPF) et Syntaxe XAML en détail.

À titre d'exemple de syntaxe autre qu'une syntaxe d'attribut, l'exemple de XAML suivant montre un autre arrière-plan de bouton. Cette fois, au lieu de définir une couleur unie, l'arrière-plan a pour valeur une image, avec un élément représentant cette image et la source de cette image spécifiée comme attribut de l'élément imbriqué. Il s'agit d'un exemple de syntaxe d'élément de propriété.

<Button Content="Button!">
  <Button.Background>
    <ImageBrush ImageSource="wavy.jpg"/>
  </Button.Background>
</Button>

La définition de valeurs de propriété de dépendance dans le code correspond en général simplement à un appel de l'implémentation SET exposée par le wrapper CLR. 

Button myButton = new Button();
myButton.Width = 200.0;

L'obtention d'une valeur de propriété correspond elle aussi essentiellement à un appel de l'implémentation GET du "wrapper" :

double whatWidth;
whatWidth = myButton.Width;

Vous pouvez également appeler directement APIsGetValue et SetValue du système de propriétés. En général, ce n'est pas nécessaire si vous utilisez des propriétés existantes (les wrappers sont plus pratiques et fournissent une meilleure exposition de la propriété pour les outils de développement), mais l'appel direct des APIs convient pour certains scénarios.

Vous pouvez également définir des propriétés en XAML et y accéder ultérieurement dans le code, à l'aide de code-behind. Pour plus d'informations, consultez Code-behind et XAML dans WPF.

Une propriété de dépendance fournit des fonctionnalités qui étendent les fonctionnalités d'une propriété par opposition à une propriété stockée par un champ. Souvent, les fonctionnalités de ce type représentent ou prennent en charge une fonctionnalité spécifique du jeu global de fonctionnalités de WPF :

Une valeur de propriété de dépendance peut être définie en référençant une ressource. Les ressources sont en général spécifiées comme valeur de la propriété Resources d'un élément racine d'une page ou de l'application (ces emplacements permettent d'accéder le plus facilement à la ressource). L'exemple suivant indique comment définir une ressource SolidColorBrush.

<DockPanel.Resources>
  <SolidColorBrush x:Key="MyBrush" Color="Gold"/>
</DockPanel.Resources>

Une fois la ressource définie, vous pouvez la référencer et l'utiliser pour fournir une valeur de propriété :

<Button Background="{DynamicResource MyBrush}" Content="I am gold" />

Cette ressource est référencée comme DynamicResource, extension de balisage (en XAML WPF, vous pouvez utiliser une référence à une ressource statique ou dynamique). Pour utiliser une référence à une ressource dynamique, vous devez définir à une propriété de dépendance de manière à ce que le système de propriétés WPF active précisément l'utilisation de la référence à une ressource dynamique. Pour plus d'informations, consultez Ressources XAML.

System_CAPS_noteRemarque

Les ressources sont traitées comme valeur locale, ce qui signifie que si vous définissez une autre valeur locale, vous supprimerez la référence à la ressource. Pour plus d'informations, consultez Priorité de la valeur de propriété de dépendance.

Une propriété de dépendance peut référencer une valeur à travers la liaison de données. La liaison de données fonctionne par le biais d'une syntaxe d'extension de balisage spécifique en XAML ou l'objet Binding dans le code. Avec la liaison de données, la dernière détermination de valeur de propriété est différée jusqu'au moment de l'exécution, la valeur étant alors obtenue d'une source de données.

L'exemple suivant définit la propriété Content 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é). La liaison elle-même spécifie la propriété source souhaitée par XPath dans la source de données.

<Button Content="{Binding XPath=Team/@TeamName}"/>
System_CAPS_noteRemarque

Les liaisons sont traitées comme valeurs locales, ce qui signifie que si vous définissez une autre valeur locale, vous supprimerez la liaison. Pour plus d'informations, consultez Priorité de la valeur de propriété de dépendance.

Les propriétés de dépendance, ou la classe DependencyObject, ne sont pas dotées d'une prise en charge native de INotifyPropertyChanged pour générer des notifications de modifications de la valeur de propriété source DependencyObject pour les opérations de liaison de données. Pour plus d'informations sur la création de propriétés à des fins de liaison de données pouvant signaler des modifications à une cible de liaison de données, consultez Vue d'ensemble de la liaison de données.

Les styles et les modèles sont deux des principaux scénarios justifiant l'utilisation de propriétés de dépendance. Les styles sont particulièrement utiles pour configurer des propriétés qui définissent l'interface utilisateur (UI) de l'application. Les styles sont en général définis en tant que ressources en XAML. Les styles interagissent avec le système de propriétés parce qu'ils contiennent en général des « méthodes setter » pour des propriétés particulières, ainsi que des « déclencheurs » qui modifient une valeur de propriété selon la valeur en temps réel d'une autre propriété.

L'exemple suivant crée un style très simple (qui serait défini à l'intérieur d'un dictionnaire Resources, non illustré), puis applique ce style directement à la propriété Style d'un Button. L'accesseur Set du style affecte la couleur verte à la propriété Background d'un Button mis en forme.


  <
  Style
   x:Key
  ="GreenButtonStyle"
  >
  <Setter Property="Control.Background" Value="Green"/>
</Style>

  <
  Button
   Style
  ="{StaticResource GreenButtonStyle}"
  >I am green!</Button>

Pour plus d'informations, consultez Application d'un style et création de modèles.

Les propriétés de dépendance peuvent être animées. Lorsqu'une animation est appliquée et s'exécute, la valeur animée a priorité sur toutes les autres valeurs (ex. valeur locale) de la propriété.

L'exemple suivant anime le Background d'une propriété Button (techniquement, le Background est animé en utilisant la syntaxe d'élément de propriété pour spécifier un SolidColorBrush vierge comme Background, puis la propriété Color de ce SolidColorBrush est la propriété qui est directement animée).

<Button>I am animated
  <Button.Background>
    <SolidColorBrush x:Name="AnimBrush"/>
  </Button.Background>
  <Button.Triggers>
    <EventTrigger RoutedEvent="Button.Loaded">
      <BeginStoryboard>
        <Storyboard>
          <ColorAnimation
            Storyboard.TargetName="AnimBrush" 
            Storyboard.TargetProperty="(SolidColorBrush.Color)"
            From="Red" To="Green" Duration="0:0:5" 
            AutoReverse="True" RepeatBehavior="Forever" />
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Button.Triggers>
</Button>

Pour plus d'informations sur l'animation de propriétés, consultez Vue d'ensemble de l'animation et Vue d'ensemble des storyboards.

Vous pouvez modifier certains comportements d'une propriété de dépendance en substituant ses métadonnées lorsque vous dérivez de la classe qui enregistre initialement la propriété de dépendance. La substitution de métadonnées repose sur l'identificateur DependencyProperty. La substitution de métadonnées ne requiert pas la réimplémentation de la propriété. La modification de métadonnées est gérée en mode natif par le système de propriétés. Chaque classe contient potentiellement les métadonnées individuelles de toutes les propriétés héritées des classes de base, et ce, type par type.

L'exemple suivant substitue les métadonnées d'une propriété de dépendance DefaultStyleKey. La substitution des métadonnées de cette propriété de dépendance fait partie d'un modèle d'implémentation qui crée des contrôles pouvant utiliser des styles par défaut provenant de thèmes.

public class SpinnerControl : ItemsControl
{
    static SpinnerControl()
    {
        DefaultStyleKeyProperty.OverrideMetadata(
            typeof(SpinnerControl), 
            new FrameworkPropertyMetadata(typeof(SpinnerControl))
        );
    }
}

Pour plus d'informations sur la substitution ou l'obtention de métadonnées de propriétés, consultez Métadonnées de propriété de dépendance.

Un élément peut hériter la valeur d'une propriété de dépendance de son parent dans l'arborescence d'objets.

System_CAPS_noteRemarque

Le comportement de l'héritage de la valeur de propriété n'est pas activé globalement pour toutes les propriétés de dépendance, parce que l'heure de calcul de l'héritage a un impact sur les performances. L'héritage de valeur de propriété est en général activé uniquement pour les propriétés où un scénario particulier suggère que l'héritage de valeur de propriété est approprié. Vous pouvez déterminer si une propriété de dépendance hérite en recherchant cette propriété de dépendance dans la section Informations sur les propriétés de dépendance du Kit de développement logiciel de référence.

L'exemple suivant illustre une liaison et définit la propriété DataContext qui spécifie la source de la liaison, ce que l'exemple de liaison ci-dessus ne montrait pas. Les liaisons suivantes dans les objets enfants n'ont pas besoin de spécifier la source. Ils peuvent utiliser la valeur héritée de DataContext dans l'objet StackPanel parent. (à la place, un objet enfant pourrait éventuellement choisir de spécifier directement son propre DataContext ou un Source dans le Binding et de ne pas utiliser délibérément la valeur héritée pour le contexte de données de ses liaisons.)

<StackPanel Canvas.Top="50" DataContext="{Binding Source={StaticResource XmlTeamsSource}}">
  <Button Content="{Binding XPath=Team/@TeamName}"/>
</StackPanel>

Pour plus d'informations, consultez Héritage de la valeur de propriété.

Un contrôle personnalisé avec des propriétés implémentées comme propriétés de dépendance bénéficiera d'une prise en charge du Concepteur WPF pour Visual Studio appropriée. Par exemple, il permettra de modifier des propriétés de dépendance directes et jointes à l'aide de la fenêtre Propriétés. Pour plus d'informations, consultez Vue d'ensemble de la création de contrôles.

Lorsque vous obtenez la valeur d'une propriété de dépendance, vous obtenez potentiellement une valeur définie pour cette propriété à l'aide de l'une des autres entrées basées sur des propriétés qui participent au système de propriétés WPF. La priorité de la valeur de la propriété de dépendance est telle que plusieurs scénarios sur la façon dont les propriétés obtiennent leurs valeurs peuvent interagir de manière prévisible.

Prenons l'exemple suivant. L'exemple inclut un style qui s'applique à tous les boutons et à leurs propriétés Background, mais qui spécifie aussi un bouton avec une valeur Background localement définie.

System_CAPS_noteRemarque

La documentation du Kit de développement logiciel utilise parfois les termes « valeur locale » et « valeur localement définie » pour désigner des propriétés de dépendance. Une valeur localement définie est une valeur de propriété définie directement dans une instance d'objet dans le code ou en tant qu'attribut d'un élément dans XAML.

En principe, la propriété est définie deux fois pour le premier bouton, mais une seule valeur s'applique : la valeur ayant la priorité la plus élevée. Une valeur localement définie a la priorité la plus élevée (à l'exception d'une animation en cours d'exécution, mais aucune animation ne s'applique dans cet exemple) et donc la valeur localement définie est utilisée au lieu de la valeur de l'accesseur Set du style pour l'arrière-plan du premier bouton. Le deuxième bouton n'a pas de valeur locale (et aucune autre valeur ayant une priorité supérieure à un accesseur Set de style) et donc, l'arrière-plan de ce bouton provient de l'accesseur Set de style.

<StackPanel>
  <StackPanel.Resources>
    <Style x:Key="{x:Type Button}" TargetType="{x:Type Button}">
     <Setter Property="Background" Value="Red"/>
    </Style>
  </StackPanel.Resources>
  <Button Background="Green">I am NOT red!</Button>
  <Button>I am styled red</Button>
</StackPanel>

En général, vous ne souhaitez pas que des styles s'appliquent dans tous les cas et viennent masquer une valeur localement définie d'un élément individuel (sinon, il serait très difficile d'utiliser des styles ou des éléments en général). Par conséquent, les valeurs qui proviennent de styles ont une priorité plus faible qu'une valeur localement définie. Pour une liste plus complète des propriétés de dépendance et de l'origine éventuelle de la valeur effective d'une propriété de dépendance, consultez Priorité de la valeur de propriété de dépendance.

System_CAPS_noteRemarque

Nombre des propriétés définies pour des éléments WPF ne sont pas des propriétés de dépendance. Dans l'ensemble, les propriétés ont été implémentées comme des propriétés de dépendance uniquement lorsqu'il fallait prendre en charge au moins l'un des scénarios autorisés par le système de propriétés : liaison de données, style, animation, prise en charge de valeur par défaut, héritage, propriétés jointes ou invalidation.

  • Une propriété jointe est un type de propriété qui prend en charge une syntaxe particulière en XAML. Souvent, une propriété attachée n'a pas de correspondance 1:1 avec une propriété Common Language Runtime (CLR) et n'est pas nécessairement une propriété de dépendance. En général, une propriété attachée a pour but de permettre à des éléments enfants de signaler des valeurs de propriété à un élément parent, même si l'élément parent et l'élément enfant ne possèdent pas tous les deux cette propriété dans le cadre des listes de membres de classe. Le scénario principal consiste à permettre aux éléments enfants d'informer le parent sur la manière dont ils doivent être présentés dans Interface utilisateur. Pour obtenir un exemple, consultez Dock ou Left. Pour plus d'informations, consultez Vue d'ensemble des propriétés jointes.

  • Les développeurs de composants ou d'applications peuvent souhaiter créer leur propre propriété de dépendance, pour activer des fonctions telles que la liaison de données ou le support de styles, ou pour l'invalidation et la prise en charge du forçage de valeur. Pour plus d'informations, consultez Propriétés de dépendance personnalisées.

  • Les propriétés de dépendance doivent en général être considérées comme des propriétés publiques, accessibles ou au moins détectables par tout appelant qui a accès à une instance. Pour plus d'informations, consultez Sécurité de propriété de dépendance.

Afficher: