Metadados de propriedade da dependência

O sistema de propriedades do Windows Presentation Foundation (WPF) inclui um sistema de relatório de metadados que vai além do que pode ser relatado sobre uma propriedade por meio de características CLR (Common Language Runtime) de reflexão ou geral. Os metadados de uma propriedade de dependência também podem ser atribuídos exclusivamente pela classe que define uma propriedade de dependência, podem ser alterados quando a propriedade de dependência é adicionada a uma classe diferente e podem ser substituídos especificamente por todas as classes derivadas que herdam a propriedade de dependência da classe base de definição.

Pré-requisitos

Este tópico pressupõe que você compreenda as propriedades de dependência da perspectiva de um consumidor de propriedades de dependência existentes em classes WPF e tenha lido a Visão geral das propriedades de dependência. Para seguir os exemplos deste tópico, você também deve ter noções básicas de XAML e saber como escrever aplicativos do WPF.

Como os metadados de propriedade de dependência são usados

Os metadados de propriedade de dependência existem como um objeto que pode ser consultado para examinar as características de uma propriedade de dependência. Esses metadados também são acessados frequentemente pelo sistema de propriedades enquanto ele processa qualquer propriedade de dependência. O objeto de metadados de uma propriedade de dependência pode conter os seguintes tipos de informações:

  • Valor padrão para a propriedade dependency, se nenhum outro valor puder ser determinado para a propriedade dependency por valor local, estilo, herança, etc. Para obter uma discussão completa de como os valores padrão participam da precedência usada pelo sistema de propriedades ao atribuir valores para propriedades de dependência, consulte Precedência de valor de propriedade de dependência.

  • Referências às implementações de retorno de chamada que afetam os comportamentos de coerção ou de notificação de alteração com base no tipo de proprietário. Observe que esses retornos de chamada são frequentemente definidos com um nível de acesso não público, de modo que obter as referências reais dos metadados geralmente não é possível, a menos que as referências estejam dentro de seu escopo de acesso permitido. Para obter mais informações sobre os retornos de chamada de propriedade de dependência, consulte Retornos de chamada de propriedade de dependência e validação.

  • Se a propriedade de dependência em questão for considerada uma propriedade de nível de estrutura do WPF, os metadados poderão conter características das propriedades de dependência no nível da estrutura do WPF, que relatam informações e estados de serviço como a lógica da herança de propriedade e do mecanismo de layout no nível da estrutura do WPF. Para obter mais informações sobre este aspecto dos metadados de propriedade de dependência, consulte Metadados de propriedade de estrutura.

APIs de metadados

O tipo que relata a maioria das informações de metadados usadas pelo sistema de propriedades é a PropertyMetadata classe. Instâncias de metadados são especificadas opcionalmente quando as propriedades de dependência são registradas no sistema de propriedades e podem ser especificadas novamente para tipos adicionais que se adicionarem como proprietários ou substituírem os metadados que eles herdam da definição de propriedade de dependência da classe base. (Para casos em que um registro de propriedade não especifica metadados, um padrão é criado com valores padrão PropertyMetadata para essa classe.) Os metadados registrados são retornados como PropertyMetadata quando você chama as várias GetMetadata sobrecargas que obtêm metadados de uma propriedade de dependência em uma DependencyObject instância.

A PropertyMetadata classe é derivada de para fornecer metadados mais específicos para divisões arquitetônicas, como as classes de nível de estrutura WPF. UIPropertyMetadata adiciona relatórios de animação e FrameworkPropertyMetadata fornece as propriedades de nível de estrutura do WPF mencionadas na seção anterior. Quando as propriedades de dependência são registradas, elas podem ser registradas com essas PropertyMetadata classes derivadas. Quando os metadados são examinados, o tipo base PropertyMetadata pode potencialmente ser convertido para as classes derivadas para que você possa examinar as propriedades mais específicas.

Observação

As características de propriedade que podem ser especificadas em FrameworkPropertyMetadata às vezes são referidas nesta documentação como "sinalizadores". Ao criar novas instâncias de metadados para uso em registros de propriedade de dependência ou substituições de metadados, você especifica esses valores usando a enumeração FrameworkPropertyMetadataOptions flagwise e, em seguida, fornece valores possivelmente concatenados da enumeração para o FrameworkPropertyMetadata construtor. No entanto, uma vez construídas, essas características de opção são expostas dentro de uma FrameworkPropertyMetadata série de propriedades booleanas em vez do valor de enumeração de construção. As propriedades boolianas permitem que você verifique cada condicional, em vez de exigirem que você aplique uma máscara a um valor de enumeração sinalizadora para obter as informações que lhe interessam. O construtor usa o concatenado FrameworkPropertyMetadataOptions para manter o comprimento da assinatura do construtor razoável, enquanto os metadados construídos reais expõem as propriedades discretas para tornar a consulta dos metadados mais intuitiva.

Quando substituir metadados, quando derivar uma classe

O sistema de propriedades WPF estabeleceu recursos para alterar algumas características das propriedades de dependência sem exigir que elas sejam totalmente reimplementadas. Isso é feito construindo uma instância diferente dos metadados de propriedade para a propriedade de dependência conforme ela existe em um tipo específico. Observe que a maioria das propriedades de dependência existentes não são propriedades virtuais, assim, "reimplementá-las" literalmente nas classes herdadas somente pode ser feito sombreando o membro existente.

Se o cenário que você está tentando habilitar para uma propriedade de dependência em um tipo não pode ser realizado modificando as características das propriedades de dependência existentes, talvez seja necessário criar uma classe derivada e, em seguida, declarar uma propriedade de dependência personalizada na sua classe derivada. Uma propriedade de dependência personalizada se comporta de forma idêntica às propriedades de dependência definidas pelas APIs do WPF. Para obter mais detalhes sobre propriedades de dependência personalizadas, consulte Propriedades de dependência personalizadas.

Uma característica notável de uma propriedade de dependência que você não pode substituir é seu tipo de valor. Se você estiver herdando uma propriedade de dependência que tenha o comportamento próximo do necessário, mas precisar de um tipo diferente para ela, será necessário implementar uma propriedade de dependência personalizada e talvez vincular as propriedades por meio de conversão de tipos ou outra implementação em sua classe personalizada. Além disso, você não pode substituir um ValidateValueCallback, existente porque esse retorno de chamada existe no próprio campo de registro e não em seus metadados.

Cenários de alteração de metadados existentes

Se você estiver trabalhando com os metadados de uma propriedade de dependência existente, um cenário comum para alterar os metadados de propriedade de dependência é alterar o valor padrão. Alterar ou adicionar retornos de chamada do sistema de propriedades é um cenário mais avançado. Você talvez queira fazer isso se sua implementação de uma classe derivada tiver diferentes inter-relações entre as propriedades de dependência. Uma das condicionais de ter um modelo de programação que dá suporte a código e uso declarativo é que as propriedades devem permitir serem definidas em qualquer ordem. Assim, todas as propriedades dependentes precisam ser definidas Just-In-Time sem contexto e não podem depender de conhecer uma ordem de configuração como pode ser encontrada em um construtor. Para obter mais informações sobre esse aspecto do sistema de propriedades, consulte Retornos de chamada de propriedade de dependência e validação. Observe que os retornos de chamada de validação não fazem parte dos metadados; eles fazem parte do identificador de propriedade de dependência. Portanto, os retornos de chamada de validação não podem ser alterados substituindo os metadados.

Em alguns casos, também convém alterar as opções de metadados de propriedade de nível de estrutura do WPF nas propriedades de dependência existentes. Essas opções comunicam determinadas condicionais conhecidas sobre as propriedades de nível de estrutura do WPF para outros processos de nível de estrutura do WPF, como o sistema de layout. A configuração das opções geralmente é feita apenas ao registrar uma nova propriedade de dependência, mas também é possível alterar os metadados da propriedade no nível da estrutura do WPF como parte de uma OverrideMetadata chamada OR AddOwner . Para obter os valores específicos a serem usados e mais informações, consulte Metadados de propriedade de estrutura. Para obter mais informações sobre como essas opções devem ser definidas para uma propriedade de dependência recém-registrada, consulte Propriedades de dependência personalizadas.

Substituindo metadados

A finalidade da substituição de metadados é principalmente que você tenha a oportunidade de alterar os vários comportamentos derivados de metadados que são aplicados à propriedade de dependência conforme ela existe no seu tipo. As razões para isso são explicadas em mais detalhes na seção Metadados. Para obter mais informações incluindo alguns exemplos de código, consulte Substituir metadados para uma propriedade de dependência.

Os metadados da propriedade podem ser fornecidos para uma propriedade de dependência durante a chamada de registro (Register). No entanto, em muitos casos, convém fornecer os metadados específicos do tipo da sua classe quando ela herda essa propriedade de dependência. Você pode fazer isso chamando o OverrideMetadata método. Para um exemplo das APIs do WPF, a classe é o tipo que primeiro registra a FrameworkElementFocusable propriedade de dependência. Mas a classe substitui os metadados da propriedade de dependência para fornecer seu próprio valor padrão inicial, alterando-o de para , e reutiliza a Control implementação originalFocusable.truefalse

Quando você substitui metadados, as diferentes características dos metadados são mescladas ou substituídas.

  • PropertyChangedCallback é mesclado. Se você adicionar um novo PropertyChangedCallback, esse retorno de chamada será armazenado nos metadados. Se você não especificar um PropertyChangedCallback na substituição, o valor de PropertyChangedCallback será promovido como uma referência do ancestral mais próximo que o especificou nos metadados.

  • O comportamento real do sistema de propriedades é PropertyChangedCallback que as implementações para todos os proprietários de metadados na hierarquia são retidas e adicionadas a uma tabela, com a ordem de execução pelo sistema de propriedades sendo que os retornos de chamada da classe mais derivada são invocados primeiro.

  • DefaultValue é substituído. Se você não especificar um DefaultValue na substituição, o valor de DefaultValue vem do ancestral mais próximo que o especificou nos metadados.

  • CoerceValueCallback as implementações são substituídas. Se você adicionar um novo CoerceValueCallback, esse retorno de chamada será armazenado nos metadados. Se você não especificar um CoerceValueCallback na substituição, o valor de CoerceValueCallback será promovido como uma referência do ancestral mais próximo que o especificou nos metadados.

  • O comportamento do sistema de propriedades é que somente os CoerceValueCallback metadados imediatos são chamados. Nenhuma referência a outras CoerceValueCallback implementações na hierarquia é mantida.

Esse comportamento é implementado pelo Merge, e pode ser substituído em classes de metadados derivadas.

Substituindo metadados de propriedade anexada

No WPF, as propriedades anexadas são implementadas como propriedades de dependência. Isso significa que elas também têm metadados de propriedade, que as classes individuais podem substituir. As considerações de escopo para uma propriedade anexada no WPF geralmente são que qualquer uma pode ter uma DependencyObject propriedade anexada definida nelas. Portanto, qualquer classe derivada pode substituir os metadados de qualquer DependencyObject propriedade anexada, pois ela pode ser definida em uma instância da classe. Você pode substituir os valores padrão, os retornos de chamada ou as propriedades de relatório de características de nível de estrutura do WPF. Se a propriedade anexada for definida em uma instância da sua classe, aquelas características de metadados de propriedade de substituição serão aplicadas. Por exemplo, você pode substituir o valor padrão, de modo que o valor de substituição seja relatado como o valor da propriedade anexada nas instâncias da sua classe, sempre que a propriedade não é definida de outra forma.

Observação

A Inherits propriedade não é relevante para propriedades anexadas.

Adicionando uma classe como um proprietário de uma propriedade de dependência existente

Uma classe pode se adicionar como um proprietário de uma propriedade de dependência que já foi registrada, usando o AddOwner método. Isso permite que a classe use uma propriedade de dependência que foi registrada originalmente para um tipo diferente. A classe adicionada, normalmente, não é uma classe derivada do tipo que registrou primeiro essa propriedade de dependência como proprietária. Na verdade, isso permite que sua classe e suas classes derivadas "herdem" uma implementação de propriedade de dependência sem que a classe proprietária original e a classe adicionada estejam na mesma hierarquia de classe verdadeira. Além disso, a classe adicionada (e também as classes derivadas) pode fornecer metadados específicos para o tipo da propriedade de dependência original.

Além de adicionar-se como proprietária por meio de métodos de utilitário do sistema de propriedades, a classe adicionada deve declarar membros públicos adicionais em si mesma para tornar a propriedade de dependência um participante completo do sistema de propriedades com exposição em código e marcação. Uma classe que adiciona uma propriedade de dependência existente tem as mesmas responsabilidades que expor o modelo de objeto para essa propriedade de dependência como uma classe que define uma nova propriedade de dependência personalizada. O primeiro membro a ser exposto é um campo identificador de propriedade de dependência. Esse campo deve ser um public static readonly campo do tipo DependencyProperty, que é atribuído ao valor de retorno da AddOwner chamada. O segundo membro a ser definido é a propriedade "wrapper" do Common Language Runtime (CLR). O wrapper torna muito mais conveniente manipular sua propriedade de dependência no código (você evita chamadas para SetValue cada vez e pode fazer essa chamada apenas uma vez no próprio wrapper). O wrapper é implementado igual seria implementado se você estivesse registrando uma propriedade de dependência personalizada. Para obter mais informações de como implementar uma propriedade de dependência, consulte Propriedades de dependência personalizadas e Adicionar um tipo de proprietário para uma propriedade de dependência.

AddOwner e propriedades anexadas

Você pode chamar AddOwner uma propriedade de dependência que é definida como uma propriedade anexada pela classe owner. Geralmente o motivo para isso é expor a propriedade anexada anteriormente como uma propriedade de dependência não anexada. Em seguida, você exporá o valor de retorno como um campo para uso como o AddOwner identificador de propriedade de dependência e definirá as propriedades "wrapper" apropriadas para que a propriedade apareça na tabela de membros e ofereça suporte a um public static readonly uso de propriedade não anexada em sua classe.

Confira também