Héritage de valeur de propriété (WPF .NET)

L’héritage des valeurs de propriété est une fonctionnalité du système de propriétés Windows Presentation Foundation (WPF) et s’applique aux propriétés de dépendance. L’héritage de valeur de propriété permet aux éléments enfants d’une arborescence d’éléments d’obtenir la valeur d’une propriété particulière à partir de l’élément parent le plus proche. Étant donné qu’un élément parent peut également avoir obtenu sa valeur de propriété par héritage de valeur de propriété, le système revient potentiellement à la racine de la page.

Le système de propriétés WPF n’active pas l’héritage de valeur de propriété par défaut et l’héritage de valeur est inactif, sauf si elle est spécifiquement activée dans les métadonnées de propriété de dépendance. Même avec l’héritage de valeur de propriété activé, un élément enfant hérite uniquement d’une valeur de propriété en l’absence d’une valeur de priorité plus élevée.

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 à connaître le langage XAML (Extensible Application Markup Language) et à savoir comment écrire des applications WPF.

Héritage via une arborescence d’éléments

L’héritage de valeur de propriété n’est pas le même concept que l’héritage de classe dans la programmation orientée objet, où les classes dérivées héritent des membres de classe de base. Ce type d’héritage est également actif dans WPF, bien que dans XAML, les propriétés de classe de base héritées soient exposées en tant qu’attributs d’éléments XAML qui représentent des classes dérivées.

L’héritage de la valeur de propriété est le mécanisme par lequel une valeur de propriété de dépendance se propage des éléments parents à enfants dans une arborescence d’éléments qui contiennent la propriété. Dans le balisage XAML, une arborescence d’éléments est visible en tant qu’éléments imbriqués.

L’exemple suivant montre les éléments imbriqués en XAML. WPF inscrit la AllowDrop propriété de dépendance sur la UIElement classe avec les métadonnées de propriété qui active l’héritage de valeur de propriété et définit la valeur falsepar défaut sur . La AllowDrop propriété de dépendance existe sur Canvas, StackPanelet Label les éléments étant donné qu’ils dérivent tous de UIElement. Étant donné que la AllowDrop propriété de dépendance sur canvas1 est définie truesur , les descendants stackPanel1 et label1 les éléments héritent true comme AllowDrop valeur.

<Canvas x:Name="canvas1" Grid.Column="0" Margin="20" Background="Orange" AllowDrop="True">
    <StackPanel Name="stackPanel1" Margin="20" Background="Green">
        <Label Name="label1" Margin="20" Height="40" Width="40" Background="Blue"/>
    </StackPanel>
</Canvas>

Vous pouvez également créer une arborescence d’éléments par programmation en ajoutant des objets d’élément à la collection d’éléments enfant d’un autre objet d’élément. Au moment de l’exécution, l’héritage de valeur de propriété fonctionne sur l’arborescence d’objets résultante. Dans l’exemple suivant, stackPanel2 est ajouté à la collection enfant de canvas2. De même, label2 est ajouté à la collection enfant de stackPanel2. Étant donné que la AllowDrop propriété de dépendance sur canvas2 est définie truesur , les descendants stackPanel2 et label2 les éléments héritent true comme AllowDrop valeur.

Canvas canvas2 = new()
{
    AllowDrop = true
};
StackPanel stackPanel2 = new();
Label label2 = new();
canvas2.Children.Add(stackPanel2);
stackPanel2.Children.Add(label2);
Dim canvas2 As New Canvas With {
    .AllowDrop = True
}
Dim stackPanel2 As New StackPanel()
Dim label2 As New Label()
canvas2.Children.Add(stackPanel2)
stackPanel2.Children.Add(label2)

Applications pratiques de l’héritage des valeurs de propriété

Les propriétés de dépendance WPF spécifiques ont l’héritage des valeurs activé par défaut, comme AllowDrop et FlowDirection. En règle générale, les propriétés avec héritage de valeur activée par défaut sont implémentées sur les classes d’éléments de l’interface utilisateur de base, de sorte qu’elles existent sur les classes dérivées. Par exemple, étant donné qu’elle AllowDrop est implémentée sur la UIElement classe de base, cette propriété de dépendance existe également sur chaque contrôle dérivé de UIElement. WPF active l’héritage des valeurs sur les propriétés de dépendance pour lesquelles il est pratique pour un utilisateur de définir la valeur de la propriété une fois sur un élément parent et que cette valeur de propriété se propage aux éléments descendants de l’arborescence d’éléments.

Le modèle d’héritage de valeur de propriété affecte des valeurs de propriété, héritées et non générées, en fonction de la priorité des valeurs de propriété de dépendance. Par conséquent, une valeur de propriété d’élément parent est appliquée uniquement à un élément enfant, si la propriété d’élément enfant n’a pas de valeur de priorité plus élevée, telle qu’une valeur définie localement ou une valeur obtenue par le biais de styles, de modèles ou de liaison de données.

La FlowDirection propriété de dépendance définit la direction de disposition des éléments de texte et d’interface utilisateur enfant dans un élément parent. En règle générale, vous vous attendez à ce que la direction du flux des éléments de texte et d’interface utilisateur d’une page soit cohérente. Étant donné que l’héritage de valeur est activé dans les métadonnées de propriété de FlowDirection, une valeur ne doit être définie qu’une seule fois en haut de l’arborescence d’éléments pour une page. Dans le cas rare où un mélange de directions de flux est destiné à une page, une autre direction de flux peut être définie sur un élément de l’arborescence en affectant une valeur définie localement. La nouvelle direction de flux se propage ensuite aux éléments descendants en dessous de ce niveau.

Rendre une propriété personnalisée héritante

Vous pouvez rendre une propriété de dépendance personnalisée héritée en activant la Inherits propriété dans une instance de FrameworkPropertyMetadata, puis en inscrivant votre propriété de dépendance personnalisée avec cette instance de métadonnées. Par défaut, Inherits est défini false sur FrameworkPropertyMetadata. L’héritage d’une valeur de propriété affecte les performances. Cette fonctionnalité n’est donc définie Inherits true que si cette fonctionnalité est nécessaire.

Lorsque vous inscrivez une propriété de dépendance avec Inherits activée dans les métadonnées, utilisez la RegisterAttached méthode comme décrit dans Inscrire une propriété jointe. Attribuez également une valeur par défaut à la propriété afin qu’une valeur héritée existe. Vous pouvez également créer un wrapper de propriétés avec get et set des accesseurs sur le type de propriétaire, comme vous le feriez pour une propriété de dépendance non attachée. De cette façon, vous pouvez définir la valeur de propriété à l’aide du wrapper de propriétés sur un type propriétaire ou dérivé. L’exemple suivant crée une propriété de dépendance nommée IsTransparent, avec Inherits activé et une valeur par défaut de false. L’exemple inclut également un wrapper de propriétés avec get et set des accesseurs.

public class Canvas_IsTransparentInheritEnabled : Canvas
{
    // Register an attached dependency property with the specified
    // property name, property type, owner type, and property metadata
    // (default value is 'false' and property value inheritance is enabled).
    public static readonly DependencyProperty IsTransparentProperty =
        DependencyProperty.RegisterAttached(
            name: "IsTransparent",
            propertyType: typeof(bool),
            ownerType: typeof(Canvas_IsTransparentInheritEnabled),
            defaultMetadata: new FrameworkPropertyMetadata(
                defaultValue: false,
                flags: FrameworkPropertyMetadataOptions.Inherits));

    // Declare a get accessor method.
    public static bool GetIsTransparent(Canvas element)
    {
        return (bool)element.GetValue(IsTransparentProperty);
    }

    // Declare a set accessor method.
    public static void SetIsTransparent(Canvas element, bool value)
    {
        element.SetValue(IsTransparentProperty, value);
    }

    // For convenience, declare a property wrapper with get/set accessors.
    public bool IsTransparent
    {
        get => (bool)GetValue(IsTransparentProperty);
        set => SetValue(IsTransparentProperty, value);
    }
}
Public Class Canvas_IsTransparentInheritEnabled
    Inherits Canvas

    ' Register an attached dependency property with the specified
    ' property name, property type, owner type, and property metadata
    ' (default value is 'false' and property value inheritance is enabled).
    Public Shared ReadOnly IsTransparentProperty As DependencyProperty =
        DependencyProperty.RegisterAttached(
            name:="IsTransparent",
            propertyType:=GetType(Boolean),
            ownerType:=GetType(Canvas_IsTransparentInheritEnabled),
            defaultMetadata:=New FrameworkPropertyMetadata(
                defaultValue:=False,
                flags:=FrameworkPropertyMetadataOptions.[Inherits]))

    ' Declare a get accessor method.
    Public Shared Function GetIsTransparent(element As Canvas) As Boolean
        Return element.GetValue(IsTransparentProperty)
    End Function

    ' Declare a set accessor method.
    Public Shared Sub SetIsTransparent(element As Canvas, value As Boolean)
        element.SetValue(IsTransparentProperty, value)
    End Sub

    ' For convenience, declare a property wrapper with get/set accessors.
    Public Property IsTransparent As Boolean
        Get
            Return GetValue(IsTransparentProperty)
        End Get
        Set(value As Boolean)
            SetValue(IsTransparentProperty, value)
        End Set
    End Property
End Class

Les propriétés jointes sont conceptuellement similaires aux propriétés globales. Vous pouvez vérifier leur valeur sur n’importe quel DependencyObject résultat et obtenir un résultat valide. Le scénario classique pour les propriétés jointes consiste à définir des valeurs de propriété sur des éléments enfants, et ce scénario est plus efficace si la propriété en question est implicitement présente en tant que propriété jointe sur chaque DependencyObject élément de l’arborescence.

Héritage des valeurs de propriété entre les limites de l’arborescence

L’héritage des propriétés fonctionne sur une arborescence d’éléments. Cette arborescence est souvent parallèle à l’arborescence logique. Toutefois, chaque fois que vous incluez un objet de niveau principal WPF, tel qu’un Brush, dans le balisage qui définit une arborescence d’éléments, vous avez créé une arborescence logique discontinue. Une arborescence logique vraie ne s’étend pas conceptuellement par le biais de l’arborescence Brushlogique, car l’arborescence logique est un concept au niveau du framework WPF. Vous pouvez utiliser les méthodes d’assistance permettant d’analyser LogicalTreeHelper et d’afficher l’étendue d’une arborescence logique. L’héritage de la valeur de propriété est en mesure de transmettre des valeurs héritées par le biais d’une arborescence logique discontinue, mais uniquement si la propriété pouvant hériter a été inscrite en tant que propriété jointe et qu’il n’existe pas de limite délibérée bloquant l’héritage, telle qu’un Frame.

Remarque

Bien que l’héritage de valeur de propriété semble fonctionner pour les propriétés de dépendance non attachées, le comportement d’héritage d’une propriété non attachée par le biais de certaines limites d’éléments dans l’arborescence runtime n’est pas défini. Chaque fois que vous spécifiez Inherits dans les métadonnées de propriété, inscrivez vos propriétés à l’aide RegisterAttachedde .

Voir aussi