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 d'enveloppe de propriété conventionnelle.
Conditions préalables
L’article suppose une connaissance de base des propriétés de dépendance et que vous avez lu 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 est une propriété jointe, car elle est définie sur les éléments enfants d’un DockPanel, et non sur le DockPanel
lui-même. La classe DockPanel
définit un champ de DependencyProperty statique, nommé DockProperty, puis fournit des méthodes GetDock et SetDock 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 DockPanel peut définir la valeur de la propriété DockPanel.Dock.
<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 que des mécanismes indirects permettent de comparer des valeurs, telles que 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 attachées WPF qui sont 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 spécifiées dans les 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 de la logique interne qui agit sur la structure d’objets arborescente, obtient les valeurs et agit sur elles.
- Le type qui définit la propriété jointe est utilisé comme élément enfant pour différents éléments parents et modèles de contenu possibles.
- Le type qui définit la propriété jointe représente un service. D’autres types définissent des valeurs pour la propriété jointe. Ensuite, lorsque l’élément qui définit la propriété est évalué dans le contexte du service, les valeurs de propriété jointes sont obtenues par le biais d’une 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 propriété jointe DockPanel.Dock. DockPanel
a du code de niveau classe, en particulier MeasureOverride et ArrangeOverride, qui fait partie de sa logique de rendu. Une instance DockPanel
vérifie 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 de DockPanel
imbriquée consiste à interagir uniquement avec sa collection d’éléments enfants 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 aucune DockPanel
.
Propriétés jointes dans le code
Les propriétés jointes dans WPF n’ont pas les méthodes de wrapper CLR standard get
et set
, car les propriétés peuvent être définies à partir de l’extérieur 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 de Get<property name>
et de 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 classe TextBox.
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 pas myTextBox
en tant qu’élément enfant de myDockPanel
, l’appel de SetDock
ne déclenchera pas d’exception et n’aura aucun effet. Seule une valeur DockPanel.Dock définie sur un élément enfant d’un DockPanel
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 au DockPanel
.
Du point de vue du code, une propriété jointe est semblable à un champ support 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 être définie au préalable 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 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 de valeur 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 contrôleur de disposition sont en mesure d’exprimer leurs exigences de disposition à leur parent contrôleur de disposition et de définir une valeur pour une propriété associée 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 avoir le support du Concepteur WPF de Visual Studio, 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 de valeur 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. Dans le cas contraire, suivez le modèle WPF d’avoir une propriété jointe comme propriété de dépendance, en dérivant votre classe de DependencyObject
.
Définissez votre propriété jointe en tant que dépendance dans la classe de définition en déclarant un champ public static readonly
de type DependencyProperty. Ensuite, affectez la valeur de retour de la méthode RegisterAttached 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 d’identificateur <property name>Property
. Fournissez également des méthodes d’accesseur statiques Get<property name>
et Set<property name>
pour permettre 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 méthode RegisterAttached et comment définir les méthodes d’accesseur. Dans l’exemple, le nom de la propriété jointe est HasFish
, de sorte que 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 signature de méthode d’accesseur get
est public static object Get<property name>(DependencyObject target)
, où :
target
est le DependencyObject à partir duquel la propriété jointe est lue. Le typetarget
peut être plus spécifique queDependencyObject
. Par exemple, la méthode d’accesseur DockPanel.GetDock définit le type detarget
comme UIElement, car la propriété jointe est destinée à être appliquée à des instances deUIElement
.UiElement
dérive indirectement deDependencyObject
.- Le type de retour peut être plus spécifique que
object
. Par exemple, la méthode GetDock tape la valeur retournée comme Dock, car la valeur de retour doit être une énumérationDock
.
Remarque
L’accesseur get
pour une propriété jointe est nécessaire 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 signature de méthode d’accesseur set
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 typetarget
peut être plus spécifique queDependencyObject
. Par exemple, la méthode SetDock tape letarget
comme UIElement, car la propriété jointe est destinée à être définie sur UIElement instances.UiElement
dérive indirectement deDependencyObject
.- Le type
value
peut être plus spécifique queobject
. Par exemple, la méthode SetDock nécessite une valeur Dock. Le chargeur XAML doit être en mesure de générer le typevalue
à 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 :
- AttachedPropertyBrowsableAttribute
- AttachedPropertyBrowsableForChildrenAttribute
- AttachedPropertyBrowsableForTypeAttribute
- AttachedPropertyBrowsableWhenAttributePresentAttribute
Pour en savoir plus
- Pour plus d’informations sur la création d’une propriété jointe, consultez Inscrire une propriété jointe.
- Pour 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 enregistrer une propriété en tant que propriété attachée et propriété de dépendance, et inclure des wrappers de propriétés classiques. De cette manière, une propriété peut être définie sur un élément à l’aide de wrappers de propriétés, ainsi que sur tout autre élément en utilisant la syntaxe de propriété attachée XAML. Pour obtenir un exemple, consultez FrameworkElement.FlowDirection.
Voir aussi
- DependencyProperty
- Vue d’ensemble des propriétés de dépendance
- propriétés de dépendance personnalisées
- XAML dans WPF
- Comment enregistrer une propriété attachée
.NET Desktop feedback