Compartilhar via


Herança do valor da propriedade (WPF .NET)

A herança do valor da propriedade é um recurso do sistema de propriedades WPF (Windows Presentation Foundation) e se aplica às 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 o valor de propriedade dele por meio da herança de valor da propriedade, o sistema potencialmente realiza a recursão de volta para a raiz da página.

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

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, ele ajuda se você estiver familiarizado com XAML (Extensible Application Markup Language) e saber como escrever aplicativos WPF.

Herança por meio de uma árvore de elementos

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

A herança do valor da 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 propriedade de dependência AllowDrop na classe UIElement com metadados de propriedade que habilita a herança do valor da propriedade e define o valor padrão como false. A propriedade de dependência AllowDrop existe em elementos Canvas, StackPanele Label, pois todos derivam de UIElement. Como a propriedade de dependência AllowDrop em canvas1 é definida como true, os elementos descendentes stackPanel1 e label1 herdam true como seu valor AllowDrop.

<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 elemento. Em tempo de execução, a herança de valor da 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 propriedade de dependência AllowDrop em canvas2 é definida como true, os elementos descendentes stackPanel2 e label2 herdam true como seu valor AllowDrop.

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 de herança de valor de propriedade

Propriedades específicas de dependência 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 elementos de interface do usuário base, portanto, elas existem em classes derivadas. Por exemplo, como AllowDrop é implementado na classe base UIElement, 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 ter esse valor de propriedade propagado para elementos descendentes na árvore de elementos.

O valor de propriedade do modelo de herança atribui valores de propriedade, herdados e não herdados, de acordo com precedência do valor de propriedade de dependência. Portanto, um valor de propriedade do 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 propriedade de dependência FlowDirection define a direção do layout dos elementos de interface do usuário filho e de texto dentro de um elemento pai. Normalmente, você esperaria que a direção do fluxo de elementos de texto e interface do usuário dentro de uma página fosse consistente. Como a herança de valor está habilitada na propriedade metadados de FlowDirection, um valor só precisa ser definido uma vez na parte superior da árvore de elementos para 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 de fluxo será propagada para elementos descendentes abaixo desse nível.

Tornando uma propriedade personalizada herdável

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

Quando você registrar uma propriedade de dependência com Inherits habilitado em metadados, use o método RegisterAttached conforme descrito em Registrar uma propriedade anexada. Além disso, atribua um valor padrão à propriedade para que exista um valor herdável. Talvez você também queira criar um wrapper de propriedade com os acessórios get e set no tipo de proprietário, 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 habilitado e um valor padrão de false. O exemplo também inclui um wrapper de propriedade com acessadores get 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 o valor deles em qualquer 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 será mais eficaz se a propriedade em questão estiver implicitamente presente como uma propriedade anexada em cada elemento DependencyObject na árvore.

Herdando valores de propriedade entre limites de árvore

A herança de propriedade funciona percorrendo uma árvore de elementos. Essa árvore geralmente é paralela à árvore lógica. No entanto, sempre que você incluir um objeto de nível fundamental do WPF, como um Brush, na marcação que define uma árvore de elementos, você criou uma árvore lógica descontinua. Uma árvore lógica verdadeira não se estende conceitualmente pelo Brush, pois 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 do valor da propriedade é capaz de passar valores herdados por meio de uma árvore lógica descontinuada, mas somente se a propriedade herdável foi registrada como uma propriedade anexada e não há um limite de bloqueio de herança deliberada, como um Frame.

Nota

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

Consulte também