Compartilhar via


Visão geral das propriedades anexadas

Uma propriedade anexada é um conceito XAML (Extensible Application Markup Language). As propriedades anexadas permitem que pares extras de propriedade/valor sejam definidos em qualquer elemento XAML que derive de DependencyObject, mesmo que o elemento não defina essas propriedades extras em seu modelo de objeto. As propriedades extras são acessíveis globalmente. As propriedades anexadas normalmente são definidas como uma forma especializada de propriedade de dependência que não possui um envoltório de propriedade convencional.

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 e saber como escrever aplicativos do WPF (Windows Presentation Foundation).

Por que usar propriedades anexadas

Uma propriedade anexada permite que um elemento filho especifique um valor exclusivo para uma propriedade definida em um elemento pai. Um cenário comum é um elemento filho que especifica como ele deve ser renderizado na interface do usuário por seu elemento pai. Por exemplo, DockPanel.Dock é uma propriedade anexada porque é definida em elementos filho de um DockPanel, não em DockPanel si. A DockPanel classe define um campo estático DependencyProperty , chamado DockProperty, e fornece GetDock e SetDock métodos como acessadores públicos para a propriedade anexada.

Propriedades anexadas em XAML

No XAML, você define as propriedades anexadas usando a sintaxe <attached property provider type>.<property name>, em que o provedor de propriedades anexadas é a classe que define a propriedade anexada. O exemplo a seguir mostra como um elemento filho de DockPanel pode atribuir o valor da propriedade DockPanel.Dock.

<DockPanel>
    <TextBox DockPanel.Dock="Top">Enter text</TextBox>
</DockPanel>

O uso é semelhante a uma propriedade estática na qual você faz referência ao tipo que possui e registra a propriedade anexada (por exemplo, DockPanel), não o nome da instância.

Quando você especifica uma propriedade anexada usando um atributo XAML, somente a ação definida é aplicável. Você não pode obter um valor de propriedade diretamente por meio de XAML, embora existam alguns mecanismos indiretos para comparar valores, como gatilhos em estilos.

Propriedades anexadas no WPF

As propriedades anexadas são um conceito XAML, as propriedades de dependência são um conceito do WPF. No WPF, a maioria das propriedades anexadas relacionadas à interface do usuário em tipos WPF são implementadas como propriedades de dependência. As propriedades anexadas do WPF, implementadas como propriedades de dependência, suportam conceitos como metadados de propriedade, incluindo valores padrão definidos pelos metadados.

Modelos de uso de propriedade anexada

Embora qualquer objeto possa definir um valor de propriedade anexado, isso não significa que definir um valor produzirá um resultado tangível ou o valor será usado por outro objeto. A principal finalidade das propriedades anexadas é fornecer uma maneira para objetos de uma ampla variedade de hierarquias de classe e relações lógicas relatarem informações comuns ao tipo que define a propriedade anexada. O uso de propriedade anexada normalmente segue um destes modelos:

  • O tipo que define a propriedade anexada é o pai dos elementos que atribuem valores à propriedade anexada. O tipo pai itera seus objetos filho por meio da lógica interna que atua na estrutura da árvore de objetos, obtém os valores e atua nesses valores de alguma forma.
  • O tipo que define a propriedade anexada é usado como o elemento filho para vários possíveis elementos pai e modelos de conteúdo.
  • O tipo que define a propriedade anexada representa um serviço. Outros tipos definem valores para a propriedade anexada. Em seguida, quando o elemento que define a propriedade é avaliado no contexto do serviço, os valores da propriedade anexada são obtidos por meio da lógica interna da classe de serviço.

Um exemplo de uma propriedade anexada definida pelo pai

O cenário típico em que o WPF define uma propriedade anexada é quando um elemento pai dá suporte a uma coleção de elementos filho e o elemento pai implementa um comportamento com base nos dados relatados por cada um de seus elementos filho.

DockPanel define a DockPanel.Dock propriedade anexada. DockPanel tem código de nível de classe, especificamente MeasureOverride e ArrangeOverride, isso faz parte de sua lógica de renderização. A DockPanel instância verifica se algum dos seus elementos filhos imediatos atribuiu um valor a DockPanel.Dock. Nesse caso, esses valores se tornam entradas para a lógica de renderização aplicada a cada elemento filho. Embora seja teoricamente possível que as propriedades anexadas influenciem elementos além do pai imediato, o comportamento definido para uma instância aninhada DockPanel é interagir apenas com sua coleção de elementos filho imediata. Portanto, se você definir DockPanel.Dock em um elemento que não possui um DockPanel pai, nenhum erro ou exceção será gerado e você criará um valor de propriedade global que não será consumido por nenhum DockPanel.

Propriedades anexadas no código

As propriedades anexadas no WPF não têm os métodos clr get e set wrapper típicos porque as propriedades podem ser definidas de fora do namespace CLR. Para permitir que um processador XAML defina esses valores ao analisar XAML, a classe que define a propriedade anexada deve implementar métodos de acessador dedicados na forma de Get<property name> e Set<property name>.

Você também pode usar os métodos de acessador dedicados para obter e definir uma propriedade anexada no código, conforme mostrado no exemplo a seguir. No exemplo, myTextBox é uma instância da TextBox classe.

DockPanel myDockPanel = new();
TextBox myTextBox = new();
myTextBox.Text = "Enter text";

// Add child element to the DockPanel.
myDockPanel.Children.Add(myTextBox);

// Set the attached property value.
DockPanel.SetDock(myTextBox, Dock.Top);
Dim myDockPanel As DockPanel = New DockPanel()
Dim myTextBox As TextBox = New TextBox()
myTextBox.Text = "Enter text"

' Add child element to the DockPanel.
myDockPanel.Children.Add(myTextBox)

' Set the attached property value.
DockPanel.SetDock(myTextBox, Dock.Top)

Se você não adicionar myTextBox como um elemento filho de myDockPanel, a chamada de SetDock não gerará uma exceção nem terá qualquer efeito. Somente um DockPanel.Dock valor definido em um elemento filho de um DockPanel pode afetar a renderização, e a renderização será a mesma se você definir o valor antes ou depois de adicionar o elemento filho ao DockPanel.

Do ponto de vista do código, uma propriedade anexada é como um campo de backup que tem acessadores de método em vez de acessadores de propriedade e pode ser definida em qualquer objeto sem precisar primeiro ser definida nesses objetos.

Metadados de propriedade anexados

Os metadados de uma propriedade anexada geralmente não são diferentes de uma propriedade de dependência. Ao registrar uma propriedade anexada, use FrameworkPropertyMetadata para especificar características da propriedade, como se a propriedade influencia a renderização ou a mensuração. Quando você especifica um valor padrão substituindo metadados de propriedade anexada, esse valor se torna o padrão para a propriedade anexada implícita em instâncias da classe de substituição. Se um valor de propriedade anexado não for definido de outra forma, o valor padrão será relatado quando a propriedade for consultada usando o Get<property name> acessador com uma instância da classe em que você especificou os metadados.

Para habilitar a herança de valor de propriedade em uma propriedade, use propriedades anexadas em vez de propriedades de dependência não anexadas. Para obter mais informações, consulte Herança do valor da propriedade.

Propriedades anexadas personalizadas

Quando criar uma propriedade anexada

A criação de uma propriedade anexada é útil quando:

  • Você precisa de um mecanismo de configuração de propriedade disponível para classes diferentes da classe de definição. Um cenário comum é para o layout da interface do usuário, por exemplo DockPanel.Dock, Panel.ZIndexe Canvas.Top são todos exemplos de propriedades de layout existentes. No cenário de layout, os elementos filho de um elemento controlador de layout podem expressar seus requisitos de layout para o pai do layout e definir um valor para uma propriedade anexada definida pelo pai.

  • Uma de suas classes representa um serviço e você deseja que outras classes integrem o serviço de forma mais transparente.

  • Você deseja suporte ao Designer WPF do Visual Studio, como a capacidade de editar uma propriedade por meio da janela Propriedades . Para obter mais informações, consulte a visão geral da criação de controle

  • Você deseja usar a herança do valor da propriedade.

Como criar uma propriedade anexada

Se sua classe definir uma propriedade anexada somente para uso por outros tipos, sua classe não precisará derivar de DependencyObject. Caso contrário, siga o modelo do WPF, no qual uma propriedade anexada também é uma propriedade de dependência, derivando sua classe de DependencyObject.

Defina sua propriedade anexada como uma dependência na classe de definição declarando um public static readonly campo do tipo DependencyProperty. Em seguida, atribua o valor retornado do RegisterAttached método ao campo, que também é conhecido como o identificador da propriedade de dependência. Siga a convenção de nomenclatura de propriedade do WPF, a fim de distinguir campos das propriedades que eles representam, nomeando o campo como <property name>Property. Além disso, forneça métodos estáticos Get<property name> e Set<property name> acessores, permitindo que o sistema de propriedades acesse sua propriedade anexada.

O exemplo a seguir mostra como registrar uma propriedade de dependência usando o RegisterAttached método e como definir os métodos do acessador. No exemplo, o nome da propriedade anexada é HasFish, portanto, o campo identificador é nomeado HasFishPropertye os métodos acessadores são nomeados GetHasFish e SetHasFish.

public class Aquarium : UIElement
{
    // Register an attached dependency property with the specified
    // property name, property type, owner type, and property metadata.
    public static readonly DependencyProperty HasFishProperty = 
        DependencyProperty.RegisterAttached(
      "HasFish",
      typeof(bool),
      typeof(Aquarium),
      new FrameworkPropertyMetadata(defaultValue: false,
          flags: FrameworkPropertyMetadataOptions.AffectsRender)
    );

    // Declare a get accessor method.
    public static bool GetHasFish(UIElement target) =>
        (bool)target.GetValue(HasFishProperty);

    // Declare a set accessor method.
    public static void SetHasFish(UIElement target, bool value) =>
        target.SetValue(HasFishProperty, value);
}
Public Class Aquarium
    Inherits UIElement

    ' Register an attached dependency property with the specified
    ' property name, property type, owner type, and property metadata.
    Public Shared ReadOnly HasFishProperty As DependencyProperty =
        DependencyProperty.RegisterAttached("HasFish", GetType(Boolean), GetType(Aquarium),
            New FrameworkPropertyMetadata(defaultValue:=False,
                flags:=FrameworkPropertyMetadataOptions.AffectsRender))

    ' Declare a get accessor method.
    Public Shared Function GetHasFish(target As UIElement) As Boolean
        Return target.GetValue(HasFishProperty)
    End Function

    ' Declare a set accessor method.
    Public Shared Sub SetHasFish(target As UIElement, value As Boolean)
        target.SetValue(HasFishProperty, value)
    End Sub

End Class

O acessador Get

A get assinatura do método acessador é public static object Get<property name>(DependencyObject target), em que:

  • target é o DependencyObject de onde a propriedade anexada é lida. O target tipo pode ser mais específico do que DependencyObject. Por exemplo, o método acessador DockPanel.GetDock define o target como UIElement porque a propriedade anexada destina-se a ser definida em instâncias de UIElement. UiElement deriva indiretamente de DependencyObject.
  • O tipo de retorno pode ser mais específico do que object. Por exemplo, o GetDock método digita o valor retornado como Dock porque o valor retornado deve ser uma Dock enumeração.

Observação

O get acessador de uma propriedade anexada é necessário para o suporte à associação de dados em ferramentas de design, como Visual Studio ou Blend para Visual Studio.

O acessador Set

A set assinatura do método acessador é public static void Set<property name>(DependencyObject target, object value), em que:

  • target é o DependencyObject no qual a propriedade anexada é definida. O target tipo pode ser mais específico do que DependencyObject. Por exemplo, o método SetDock tipa o target como UIElement porque a propriedade anexada é destinada a ser definida em instâncias de UIElement. UiElement deriva indiretamente de DependencyObject.
  • O value tipo pode ser mais específico do que object. Por exemplo, o SetDock método requer um Dock valor. O carregador XAML precisa ser capaz de gerar o tipo value a partir da string de marcação que representa o valor da propriedade anexada. Portanto, deve haver conversão de tipo, serializador de valor ou suporte para extensões de marcação para o tipo que você utiliza.

Atributos de propriedade anexada

O WPF define vários atributos do .NET que fornecem informações sobre propriedades anexadas a processos de reflexão e também aos consumidores de informações de reflexão e propriedade, como designers. Os designers usam atributos do .NET definidos pelo WPF para limitar as propriedades mostradas na janela de propriedades, para evitar sobrecarregar os usuários com uma lista global de todas as propriedades anexadas. Você pode considerar aplicar esses atributos às suas propriedades personalizadas anexadas. A finalidade e a sintaxe dos atributos .NET são descritas nestas páginas de referência:

Saiba Mais

  • Para obter mais informações sobre como criar uma propriedade anexada, consulte Registrar uma propriedade anexada.
  • Para cenários de uso mais avançados para propriedades de dependência e propriedades anexadas, consulte propriedades de dependência personalizadas.
  • Você pode registrar uma propriedade como uma propriedade anexada e como uma propriedade de dependência, além de incluir wrappers de propriedade convencionais. Dessa forma, uma propriedade pode ser definida em um elemento usando empacotadores de propriedade e, também, em qualquer outro elemento através da sintaxe de propriedade anexada do XAML. Para obter um exemplo, consulte FrameworkElement.FlowDirection.

Consulte também