Vue d’ensemble des propriétés jointes (WPF .NET)

Une propriété jointe est un concept XAML (Extensible Application Markup Language). Les propriétés jointes permettent aux paires propriété/valeur supplémentaires d’être définies sur n’importe quel élément XAML qui dérive de DependencyObject, même si l’élément ne définit pas ces propriétés supplémentaires dans son modèle objet. Les propriétés supplémentaires sont globalement accessibles. Les propriétés jointes sont généralement définies comme une forme spécialisée de propriété de dépendance qui n’a pas de wrapper de propriété conventionnelle.

Important

La documentation du Guide du bureau pour .NET 7 et .NET 6 est en cours de construction.

Prérequis

L’article suppose une connaissance de base des propriétés de dépendance et que vous avez lu la vue d’ensemble des propriétés de dépendance. Pour suivre les exemples de cet article, il vous aide si vous êtes familiarisé avec XAML et savez comment écrire des applications Windows Presentation Foundation (WPF).

Pourquoi utiliser des propriétés jointes

Une propriété jointe permet à un élément enfant de spécifier une valeur unique pour une propriété définie dans un élément parent. Un scénario courant est un élément enfant spécifiant comment il doit être rendu dans l’interface utilisateur par son élément parent. Par exemple, DockPanel.Dock il s’agit d’une propriété jointe, car elle est définie sur les éléments enfants d’un DockPanel, et non sur les DockPanel éléments enfants. La DockPanel classe définit un champ statiqueDependencyProperty, nomméDockProperty, puis fournit et SetDock des GetDock méthodes en tant qu’accesseurs publics pour la propriété jointe.

Propriétés jointes en XAML

En XAML, vous définissez des propriétés jointes à l’aide de la syntaxe <attached property provider type>.<property name>, où le fournisseur de propriétés attaché est la classe qui définit la propriété jointe. L’exemple suivant montre comment un élément enfant de peut définir la valeur de DockPanel la DockPanel.Dock propriété.

<DockPanel>
    <TextBox DockPanel.Dock="Top">Enter text</TextBox>
</DockPanel>

L’utilisation est similaire à une propriété statique dans laquelle vous référencez le type propriétaire et inscrit la propriété jointe (par exemple, DockPanel), et non le nom de l’instance.

Lorsque vous spécifiez une propriété jointe à l’aide d’un attribut XAML, seule l’action set est applicable. Vous ne pouvez pas obtenir directement une valeur de propriété via XAML, bien qu’il existe des mécanismes indirects pour comparer des valeurs, comme les déclencheurs dans les styles.

Propriétés jointes dans WPF

Les propriétés jointes sont un concept XAML, les propriétés de dépendance sont un concept WPF. Dans WPF, la plupart des propriétés jointes liées à l’interface utilisateur sur les types WPF sont implémentées en tant que propriétés de dépendance. Les propriétés jointes WPF implémentées en tant que propriétés de dépendance prennent en charge les concepts de propriété de dépendance, tels que les métadonnées de propriété, y compris les valeurs par défaut des métadonnées.

Modèles d’utilisation des propriétés jointes

Bien que n’importe quel objet puisse définir une valeur de propriété jointe, cela ne signifie pas que la définition d’une valeur produit un résultat tangible ou que la valeur sera utilisée par un autre objet. L’objectif principal des propriétés jointes est de fournir un moyen pour les objets d’une grande variété de hiérarchies de classes et de relations logiques pour signaler des informations communes au type qui définit la propriété jointe. L’utilisation des propriétés jointes suit généralement l’un des modèles suivants :

  • Le type qui définit la propriété jointe est le parent des éléments qui définissent des valeurs pour la propriété jointe. Le type parent itère ses objets enfants par le biais d’une logique interne qui agit sur la structure de l’arborescence d’objets, obtient les valeurs et agit sur ces valeurs d’une certaine manière.
  • Le type qui définit la propriété jointe est utilisé comme élément enfant pour différents éléments parents possibles et con mode tente ls.
  • Le type qui définit la propriété jointe représente un service. D’autres types définissent les valeurs de la propriété jointe. Quand l’élément qui définit la propriété est évalué dans le contexte du service, les valeurs de la propriété jointe sont obtenues par le biais de la logique interne de la classe de service.

Exemple de propriété jointe définie par le parent

Le scénario classique où WPF définit une propriété jointe est lorsqu’un élément parent prend en charge une collection d’éléments enfants et que l’élément parent implémente un comportement basé sur les données signalées par chacun de ses éléments enfants.

DockPanel définit la DockPanel.Dock propriété jointe. DockPanel a du code au niveau de la classe, en particulier MeasureOverride et ArrangeOverride, qui fait partie de sa logique de rendu. Une DockPanel instance case activée si l’un de ses éléments enfants immédiats a défini une valeur pour DockPanel.Dock. Dans ce cas, ces valeurs deviennent des entrées dans la logique de rendu appliquée à chaque élément enfant. Bien qu’il soit théoriquement possible pour les propriétés jointes d’influencer les éléments au-delà du parent immédiat, le comportement défini pour une instance imbriquée DockPanel consiste uniquement à interagir avec sa collection d’éléments enfant immédiate. Par conséquent, si vous définissez DockPanel.Dock sur un élément qui n’a aucun DockPanel parent, aucune erreur ou exception n’est générée et vous avez créé une valeur de propriété globale qui ne sera consommée par aucun DockPanel.

Propriétés jointes dans le code

Les propriétés jointes dans WPF n’ont pas les méthodes CLR et set wrapper get classiques, car les propriétés peuvent être définies en dehors de l’espace de noms CLR. Pour permettre à un processeur XAML de définir ces valeurs lors de l’analyse XAML, la classe qui définit la propriété jointe doit implémenter des méthodes d’accesseur dédiées sous la forme et Get<property name>Set<property name>.

Vous pouvez également utiliser les méthodes d’accesseur dédiées pour obtenir et définir une propriété jointe dans le code, comme illustré dans l’exemple suivant. Dans l’exemple, myTextBox est une instance de la TextBox classe.

DockPanel myDockPanel = new();
TextBox myTextBox = new();
myTextBox.Text = "Enter text";

// Add child element to the DockPanel.
myDockPanel.Children.Add(myTextBox);

// Set the attached property value.
DockPanel.SetDock(myTextBox, Dock.Top);
Dim myDockPanel As DockPanel = New DockPanel()
Dim myTextBox As TextBox = New TextBox()
myTextBox.Text = "Enter text"

' Add child element to the DockPanel.
myDockPanel.Children.Add(myTextBox)

' Set the attached property value.
DockPanel.SetDock(myTextBox, Dock.Top)

Si vous n’ajoutez myTextBox pas en tant qu’élément enfant, myDockPanell’appel SetDock ne déclenche pas d’exception ou n’a aucun effet. Seule une DockPanel.Dock valeur définie sur un élément enfant d’un DockPanel élément peut affecter le rendu et le rendu sera identique si vous définissez la valeur avant ou après l’ajout de l’élément enfant à l’élément DockPanelenfant.

Du point de vue du code, une propriété jointe est semblable à un champ de stockage qui a des accesseurs de méthode au lieu d’accesseurs de propriété, et peut être définie sur n’importe quel objet sans avoir d’abord besoin d’être défini sur ces objets.

Métadonnées de propriété jointes

Les métadonnées d’une propriété jointe ne sont généralement pas différentes de celles d’une propriété de dépendance. Lors de l’inscription d’une propriété jointe, utilisez FrameworkPropertyMetadata cette option pour spécifier les caractéristiques de la propriété, par exemple si la propriété affecte le rendu ou la mesure. Lorsque vous spécifiez une valeur par défaut en substituant les métadonnées de propriété jointe, cette valeur devient la valeur par défaut pour la propriété jointe implicite sur les instances de la classe de substitution. Si aucune valeur de propriété jointe n’est définie, la valeur par défaut est signalée lorsque la propriété est interrogée à l’aide de l’accesseur Get<property name> avec une instance de la classe où vous avez spécifié les métadonnées.

Pour activer l’héritage de valeur de propriété sur une propriété, utilisez des propriétés jointes au lieu de propriétés de dépendance non attachées. Pour plus d’informations, consultez Héritage des valeurs de propriété.

Propriétés jointes personnalisées

Quand créer une propriété jointe

La création d’une propriété jointe est utile lorsque :

  • Vous avez besoin d’un mécanisme de paramètre de propriété disponible pour les classes autres que la classe de définition. Un scénario courant est destiné à la disposition de l’interface utilisateur, par exemple DockPanel.Dock, Panel.ZIndexet Canvas.Top sont tous des exemples de propriétés de disposition existantes. Dans le scénario de disposition, les éléments enfants d’un élément de contrôle de disposition sont en mesure d’exprimer les exigences de disposition à leur parent de disposition et de définir une valeur pour une propriété jointe définie par le parent.

  • L’une de vos classes représente un service et vous souhaitez que d’autres classes intègrent le service de manière plus transparente.

  • Vous souhaitez que le Concepteur WPF Visual Studio prend en charge, par exemple la possibilité de modifier une propriété via la fenêtre Propriétés . Pour plus d’informations, consultez vue d’ensemble de la création de contrôles.

  • Vous souhaitez utiliser l’héritage des valeurs de propriété.

Comment créer une propriété jointe

Si votre classe définit une propriété jointe uniquement pour une utilisation par d’autres types, votre classe n’a pas besoin de dériver de DependencyObject. Sinon, suivez le modèle WPF d’avoir une propriété jointe également être une propriété de dépendance, en dérivant votre classe à partir de DependencyObject.

Définissez votre propriété jointe en tant que dépendance dans la classe de définition en déclarant un public static readonly champ de type DependencyProperty. Ensuite, affectez la valeur de retour de la RegisterAttached méthode au champ, également appelé identificateur de propriété de dépendance. Suivez la convention d’affectation de noms de propriété WPF qui distingue les champs des propriétés qu’ils représentent, en nommant le champ <property name>Propertyd’identificateur . Fournissez également des méthodes statiques Get<property name> et Set<property name> d’accesseur, qui permettent au système de propriétés d’accéder à votre propriété jointe.

L’exemple suivant montre comment inscrire une propriété de dépendance à l’aide de la RegisterAttached méthode et comment définir les méthodes d’accesseur. Dans l’exemple, le nom de la propriété jointe est HasFish, donc le champ d’identificateur est nommé HasFishProperty, et les méthodes d’accesseur sont nommées GetHasFish et SetHasFish.

public class Aquarium : UIElement
{
    // Register an attached dependency property with the specified
    // property name, property type, owner type, and property metadata.
    public static readonly DependencyProperty HasFishProperty = 
        DependencyProperty.RegisterAttached(
      "HasFish",
      typeof(bool),
      typeof(Aquarium),
      new FrameworkPropertyMetadata(defaultValue: false,
          flags: FrameworkPropertyMetadataOptions.AffectsRender)
    );

    // Declare a get accessor method.
    public static bool GetHasFish(UIElement target) =>
        (bool)target.GetValue(HasFishProperty);

    // Declare a set accessor method.
    public static void SetHasFish(UIElement target, bool value) =>
        target.SetValue(HasFishProperty, value);
}
Public Class Aquarium
    Inherits UIElement

    ' Register an attached dependency property with the specified
    ' property name, property type, owner type, and property metadata.
    Public Shared ReadOnly HasFishProperty As DependencyProperty =
        DependencyProperty.RegisterAttached("HasFish", GetType(Boolean), GetType(Aquarium),
            New FrameworkPropertyMetadata(defaultValue:=False,
                flags:=FrameworkPropertyMetadataOptions.AffectsRender))

    ' Declare a get accessor method.
    Public Shared Function GetHasFish(target As UIElement) As Boolean
        Return target.GetValue(HasFishProperty)
    End Function

    ' Declare a set accessor method.
    Public Shared Sub SetHasFish(target As UIElement, value As Boolean)
        target.SetValue(HasFishProperty, value)
    End Sub

End Class

Accesseur Get

La get signature de la méthode d’accesseur est public static object Get<property name>(DependencyObject target), où :

  • target est la DependencyObject propriété jointe à partir de laquelle la propriété jointe est lue. Le target type peut être plus spécifique que DependencyObject. Par exemple, la DockPanel.GetDock méthode d’accesseur tape comme targetUIElement étant donné que la propriété jointe est destinée à être définie sur UIElement des instances. UiElement dérive indirectement de DependencyObject.
  • Le type de retour peut être plus spécifique que object. Par exemple, la GetDock méthode tape la valeur retournée comme étant donné que Dock la valeur de retour doit être une Dock énumération.

Remarque

L’accesseur get d’une propriété jointe est requis pour la prise en charge de la liaison de données dans les outils de conception, tels que Visual Studio ou Blend pour Visual Studio.

Accesseur Set

La set signature de la méthode d’accesseur est public static void Set<property name>(DependencyObject target, object value), où :

  • target est le DependencyObject sur lequel la propriété jointe est écrite. Le target type peut être plus spécifique que DependencyObject. Par exemple, la SetDock méthode tape comme targetUIElement étant donné que la propriété jointe est destinée à être définie sur UIElement des instances. UiElement dérive indirectement de DependencyObject.
  • Le value type peut être plus spécifique que object. Par exemple, la SetDock méthode nécessite une Dock valeur. Le chargeur XAML doit être en mesure de générer le value type à partir de la chaîne de balisage qui représente la valeur de propriété jointe. Par conséquent, il doit y avoir une conversion de type, un sérialiseur de valeur ou une prise en charge de l’extension de balisage pour le type que vous utilisez.

Attributs de propriété attachés

WPF définit plusieurs attributs .NET qui fournissent des informations sur les propriétés jointes aux processus de réflexion, ainsi qu’aux consommateurs d’informations sur la réflexion et les propriétés, comme les concepteurs. Les concepteurs utilisent des attributs .NET définis par WPF pour limiter les propriétés affichées dans la fenêtre des propriétés, afin d’éviter d’accablant les utilisateurs disposant d’une liste globale de toutes les propriétés jointes. Vous pouvez envisager d’appliquer ces attributs à vos propres propriétés jointes personnalisées. L’objectif et la syntaxe des attributs .NET sont décrits dans ces pages de référence :

En savoir plus

  • Pour plus d’informations sur la création d’une propriété jointe, consultez Inscrire une propriété jointe.
  • Pour obtenir des scénarios d’utilisation plus avancés pour les propriétés de dépendance et les propriétés jointes, consultez Propriétés de dépendance personnalisées.
  • Vous pouvez inscrire une propriété en tant que propriété jointe et propriété de dépendance, et inclure des wrappers de propriétés classiques. De cette façon, une propriété peut être définie sur un élément à l’aide de wrappers de propriétés, ainsi que sur n’importe quel autre élément à l’aide de la syntaxe de propriété jointe XAML. Pour obtenir un exemple, consultez FrameworkElement.FlowDirection.

Voir aussi