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

L’héritage de la valeur 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 la 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é via l’héritage de la valeur de propriété, le système peut potentiellement revenir à la racine de la page.

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

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 vue d’ensemble des propriétés de dépendance. Pour suivre les exemples de cet article, il est utile si vous êtes familiarisé avec XAML (Extensible Application Markup Language) et que vous savez 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 la classe de base. Ce type d’héritage est également actif dans WPF, bien qu’en 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 d’éléments parent à 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 des éléments imbriqués en XAML. WPF inscrit la propriété de dépendance sur la AllowDrop classe avec des UIElementmétadonnées de propriété qui active l’héritage de la valeur de propriété et définit la valeur par défaut sur false. La AllowDrop propriété de dépendance existe sur Canvasles éléments , StackPanelet , car Label ils dérivent tous de UIElement. Étant donné que la AllowDrop propriété de dépendance sur canvas1 a la truevaleur , les éléments descendants stackPanel1 et label1 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 élément. Au moment de l’exécution, l’héritage de la 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 a la truevaleur , les éléments descendants stackPanel2 et label2 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 de la valeur de propriété

Les propriétés de dépendance WPF spécifiques ont l’héritage de valeur activé par défaut, comme AllowDrop et FlowDirection. En règle générale, les propriétés dont l’héritage de valeur est activé par défaut sont implémentées sur les classes d’éléments d’interface utilisateur de base, de sorte qu’elles existent sur les classes dérivées. Par exemple, étant AllowDrop donné que 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 de valeur 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 de faire que cette valeur de propriété se propage aux éléments descendants dans 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 héritées, en fonction de la priorité de la valeur de propriété de dépendance. Par conséquent, une valeur de propriété d’élément parent n’est appliquée qu’à un élément enfant, si la propriété d’élément enfant n’a pas de valeur de priorité supérieure, telle qu’une valeur définie localement, ou une valeur obtenue via des styles, des modèles ou une liaison de données.

La FlowDirection propriété de dépendance définit le sens de disposition des éléments de texte et d’interface utilisateur enfants au sein d’un élément parent. En règle générale, vous vous attendez à ce que le sens du flux des éléments de texte et d’interface utilisateur au sein d’une page soit cohérent. É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 les rares cas où une combinaison de directions de flux est destinée à une page, une direction de flux différente 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éritable

Vous pouvez rendre une propriété de dépendance personnalisée héritable en activant la Inherits propriété dans un instance de , puis en inscrivant votre propriété de FrameworkPropertyMetadatadépendance personnalisée avec cette métadonnées instance. Par défaut, Inherits est défini sur false dans FrameworkPropertyMetadata. Le fait de rendre une valeur de propriété héritable affecte les performances. Par conséquent, définissez Inherits uniquement sur true si cette fonctionnalité est nécessaire.

Lorsque vous inscrivez une propriété de dépendance avec Inherits activé dans les métadonnées, utilisez la RegisterAttached méthode décrite dans Inscrire une propriété jointe. En outre, affectez une valeur par défaut à la propriété afin qu’une valeur pouvant être héritée existe. Vous pouvez également créer un wrapper de propriétés avec get des accesseurs et set 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 la 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 des accesseurs et set .

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 case activée leur valeur sur n’importe quel DependencyObject 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ériter des valeurs de propriété au-delà des limites d’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 Brushobjet , dans le balisage qui définit une arborescence d’éléments, vous avez créé une arborescence logique discontinue. Une véritable arborescence logique ne s’étend pas conceptuellement via , Brushcar l’arborescence logique est un concept au niveau de l’infrastructure WPF. Vous pouvez utiliser les méthodes d’assistance de LogicalTreeHelper pour analyser et 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 via une arborescence logique discontinue, mais uniquement si la propriété pouvant être héritée a été inscrite en tant que propriété jointe et qu’il n’existe pas de limite de blocage délibéré de l’héritage, telle qu’un Frame.

Notes

Bien que l’héritage de la valeur de propriété puisse sembler fonctionner pour les propriétés de dépendance non attachées, le comportement d’héritage d’une propriété non attachée via certaines limites d’éléments dans l’arborescence du 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 de RegisterAttached.

Voir aussi