Compartilhar via


Herança de valor de propriedade (WPF .NET)

A herança de valor de propriedade é um recurso do sistema de propriedades do Windows Presentation Foundation (WPF) e se aplica a propriedades de dependência. A herança de valor de propriedade permite que elementos filho em uma árvore de elementos obtenham o valor de uma propriedade específica do elemento pai mais próximo. Como um elemento pai também pode ter obtido seu valor de propriedade por meio da herança de valor de propriedade, o sistema potencialmente recorre de volta à raiz da página.

O sistema de propriedades do WPF não habilita a herança de valor de propriedade por padrão, e a herança de valor está inativa, a menos que seja especificamente habilitada em metadados de propriedade de dependência. Mesmo com a herança de valor de propriedade habilitada, um elemento filho só herdará um valor de propriedade na ausência de um valor de precedência mais alto.

Pré-requisitos

O artigo pressupõe um conhecimento básico das propriedades de dependência e que você leu Visão geral das propriedades de dependência. Para seguir os exemplos neste artigo, é útil se você estiver familiarizado com XAML (Extensible Application Markup Language) e souber como escrever aplicativos WPF.

Herança por meio de uma árvore de elementos

A herança de valor de propriedade não é o mesmo conceito que a herança de classe na programação orientada a objetos, em que as classes derivadas herdam membros da classe base. Esse tipo de herança também está ativo no WPF, embora no XAML as propriedades de classe base herdadas sejam expostas como atributos de elementos XAML que representam classes derivadas.

A herança de valor de propriedade é o mecanismo pelo qual um valor de propriedade de dependência se propaga de elementos pai para filho dentro de uma árvore de elementos que contêm a propriedade. Na marcação XAML, uma árvore de elementos é visível como elementos aninhados.

O exemplo a seguir mostra elementos aninhados em XAML. O WPF registra a AllowDrop propriedade de dependência na classe com metadados de propriedade que permitem a UIElement herança do valor da propriedade e define o valor padrão como false. A AllowDrop propriedade de dependência existe em Canvas, StackPanel, e Label elementos, uma vez que todos eles derivam de UIElement. Como a AllowDrop propriedade de dependência em canvas1 é definida como true, o descendente stackPanel1 e label1 os elementos herdam true como seu AllowDrop valor.

<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>

Você também pode criar uma árvore de elementos programaticamente adicionando objetos de elemento à coleção de elementos filho de outro objeto de elemento. Em tempo de execução, a herança de valor de propriedade opera na árvore de objetos resultante. No exemplo a seguir, stackPanel2 é adicionado à coleção filho de canvas2. Da mesma forma, label2 é adicionado à coleção filho de stackPanel2. Como a AllowDrop propriedade de dependência em canvas2 é definida como true, o descendente stackPanel2 e label2 os elementos herdam true como seu AllowDrop valor.

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)

Aplicações práticas da herança de valor de propriedade

Propriedades de dependência específicas do WPF têm herança de valor habilitada por padrão, como AllowDrop e FlowDirection. Normalmente, as propriedades com herança de valor habilitada por padrão são implementadas em classes de elemento de interface do usuário base, portanto, existem em classes derivadas. Por exemplo, como AllowDrop é implementado na UIElement classe base, essa propriedade de dependência também existe em todos os controles derivados de UIElement. O WPF permite a herança de valor em propriedades de dependência para as quais é conveniente para um usuário definir o valor da propriedade uma vez em um elemento pai e fazer com que esse valor de propriedade se propague para elementos descendentes na árvore de elementos.

O modelo de herança de valor de propriedade atribui valores de propriedade, herdados e não herdados, de acordo com a precedência do valor da propriedade de dependência. Portanto, um valor de propriedade de elemento pai só será aplicado a um elemento filho, se a propriedade do elemento filho não tiver um valor de precedência mais alto, como um valor definido localmente ou um valor obtido por meio de estilos, modelos ou associação de dados.

A FlowDirection propriedade de dependência define a direção do layout do texto e dos elementos da interface do usuário filho em um elemento pai. Normalmente, você esperaria que a direção do fluxo de texto e elementos de interface do usuário em uma página fosse consistente. Como a herança de valor está habilitada nos metadados de propriedade de FlowDirection, um valor só precisa ser definido uma vez na parte superior da árvore de elementos de uma página. No caso raro em que uma combinação de direções de fluxo é destinada a uma página, uma direção de fluxo diferente pode ser definida em um elemento na árvore, atribuindo um valor definido localmente. A nova direção do fluxo se propagará para elementos descendentes abaixo desse nível.

Tornando uma propriedade personalizada herdável

Você pode tornar uma propriedade de dependência personalizada hereditária habilitando a Inherits propriedade em uma instância de e, em seguida, registrando sua propriedade de dependência personalizada com essa instância de FrameworkPropertyMetadatametadados. Por padrão, Inherits é definido como false em FrameworkPropertyMetadata. Tornar um valor de propriedade hereditário afeta o desempenho, portanto, defina Inherits apenas se true esse recurso for necessário.

Ao registrar uma propriedade de dependência com Inherits enabled in metadata, use o RegisterAttached método conforme descrito em Registrar uma propriedade anexada. Além disso, atribua um valor padrão à propriedade para que exista um valor herdável. Você também pode querer criar um wrapper de propriedade com get acessadores and set no tipo owner, assim como faria para uma propriedade de dependência não anexada. Dessa forma, você pode definir o valor da propriedade usando o wrapper de propriedade em um proprietário ou tipo derivado. O exemplo a seguir cria uma propriedade de dependência chamada IsTransparent, com Inherits enabled e um valor padrão de false. O exemplo também inclui um wrapper de propriedade com get acessadores e 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

As propriedades anexadas são conceitualmente semelhantes às propriedades globais. Você pode verificar seu valor em qualquer um DependencyObject e obter um resultado válido. O cenário típico para propriedades anexadas é definir valores de propriedade em elementos filho, e esse cenário é mais eficaz se a propriedade em questão estiver implicitamente presente como uma propriedade anexada em cada DependencyObject elemento na árvore.

Herdar valores de propriedade entre limites de árvore

A herança de propriedade funciona percorrendo uma árvore de elementos. Esta árvore geralmente é paralela à árvore lógica. No entanto, sempre que você inclui um objeto de nível central do WPF, como um Brush, na marcação que define uma árvore de elementos, você cria uma árvore lógica descontínua. Uma árvore lógica verdadeira não se estende conceitualmente por meio do Brush, porque a árvore lógica é um conceito de nível de estrutura do WPF. Você pode usar os métodos auxiliares de LogicalTreeHelper para analisar e exibir a extensão de uma árvore lógica. A herança de valor de propriedade é capaz de passar valores herdados por meio de uma árvore lógica descontínua, mas somente se a propriedade hereditária tiver sido registrada como uma propriedade anexada e não houver um limite de bloqueio de herança deliberado, como um Frame.

Observação

Embora a herança de valor de propriedade possa parecer funcionar para propriedades de dependência não anexadas, o comportamento de herança para uma propriedade não anexada por meio de alguns limites de elemento na árvore de tempo de execução é indefinido. Sempre que você especificar Inherits nos metadados da propriedade, registre suas propriedades usando RegisterAttached.

Confira também