Compartilhar via


Herança do valor da propriedade

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 do valor da propriedade permite que elementos filho na estrutura hierárquica obtenham o valor de uma propriedade específica do pai mais próximo na hierarquia. 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 valores de propriedade por padrão, e a herança de valores está inativa, a menos que especificamente habilitada nos metadados da propriedade de dependência. Mesmo com a herança do valor da propriedade ativada, um elemento filho só herdará o valor de uma 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, 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 AllowDrop propriedade de dependência na UIElement classe com metadados de propriedade que permitem a herança do valor da propriedade e define o valor padrão como false. A AllowDrop propriedade de dependência existe em Canvas, StackPanele Label elementos, uma vez que todos eles derivam de UIElement. Como a propriedade de dependência AllowDrop está definida como canvas1 no true, os elementos descendentes stackPanel1 e label1 herdam true como o 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 ao adicionar objetos de elementos à coleção de elementos filhos de outro objeto de elemento. Em tempo de execução, a herança do 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 de filhos de stackPanel2. Como a propriedade de dependência AllowDrop está definida como canvas2 no true, os elementos descendentes stackPanel2 e label2 herdam true como o 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 é implementada 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 ter esse valor de propriedade propagado para elementos descendentes na árvore de elementos.

O modelo de herança do valor da propriedade atribui valores de propriedade, herdados e não herdados, de acordo com a precedência da precedência do valor da 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 FlowDirection propriedade de dependência define a direção de layout do texto e dos elementos de interface do usuário filho 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 nos metadados da propriedade, FlowDirectionum 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 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 FrameworkPropertyMetadata, e depois registrando sua propriedade de dependência personalizada nessa instância de metadados. Por padrão, Inherits é definido como false em FrameworkPropertyMetadata. Tornar um valor de propriedade herdável afeta o desempenho, portanto, somente definido Inherits como true se esse recurso for necessário.

Ao registrar uma propriedade de dependência com os metadados Inherits habilitados, 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. Você também pode querer criar um wrapper de propriedade com get e set acessadores no tipo de proprietário, assim como faria para uma propriedade de dependência não anexada. Desse modo, você pode definir o valor da propriedade usando o envoltório 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 get e set acessadores.

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 DependencyObject elemento na árvore.

Herdando valores de propriedade entre limites de árvore

A herança de propriedade funciona atravessando uma árvore de elementos. Essa árvore geralmente é paralela à árvore lógica. No entanto, sempre que você incluir um objeto de nível de núcleo do WPF, como um Brush, na marcação que define uma árvore de elementos, você criou uma árvore lógica descontinuada. Uma árvore lógica verdadeira não se estende conceitualmente pelo 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 do valor da propriedade pode transmitir valores herdados através de uma árvore lógica descontínua, mas apenas se a propriedade herdável tiver sido registrada como uma propriedade anexada e não houver um limite deliberado de bloqueio de herança, como um Frame.

Observação

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

Consulte também