Compartilhar via


XAML e classes personalizadas

Extensible Application Markup Language (XAML) oferece suporte à capacidade para definir uma classe personalizada ou estrutura em qualquer linguagem common language runtime (CLR) e, em seguida, acessar essa classe usando marcação XAML, incluindo o uso de uma mistura de XAML definidas no Windows Presentation Foundation (WPF) e as marcas XAML personalizadas da classe dentro do mesmo arquivo de marcação. Este tópico aborda os requisitos que uma classe personalizada deve satisfazer para ser útil como um elemento XAML.

Este tópico contém as seguintes seções.

  • Classes personalizadas em aplicativos ou assemblies
  • Requisitos para uma classe personalizada como um elemento XAML
  • Requisitos para as propriedades de uma classe personalizada como atributos XAML
  • Requisitos para sintaxes de atributos de manipuladores de eventos XAML em eventos de uma classe personalizada
  • Escrevendo Propriedades de Coleção
  • Declarando propriedades de conteúdo XAML
  • Serializando XAML
  • Tópicos relacionados

Classes personalizadas em aplicativos ou assemblies

Classes personalizadas que são usados em XAML podem ser definidos de duas maneiras distintas: no code-behind ou Outros código que produz o principal Windows Presentation Foundation (WPF) aplicativo, ou sistema autônomo uma classe em um assembly separado, sistema autônomo um executável ou DLL usada sistema autônomo uma biblioteca de classes. Cada uma dessas abordagens possui determinadas vantagens e desvantagens.

  • A vantagem de criar uma biblioteca de classes é que quaisquer dessas classes personalizadas podem ser compartilhadas entre vários aplicativos possíveis diferentes. Uma biblioteca separada também facilita o controle de problemas de versão de aplicativos e simplifica criando uma classe que você pretende usar como um elemento raiz em uma página XAML.

  • A vantagem de definir as classes personalizadas no aplicativo é que essa técnica é relativamente simples e minimiza a implantação e problemas de testes encontrados quando apresentados assemblies separados além do executável principal. No entanto, uma notável desvantagem é que você não pode usar as classes definidas no mesmo assembly como o elemento raiz de uma página XAML.

  • Se definido no assembly iguais ou diferente, classes personalizadas precisam ser mapeados entre o namespace CLR e o espaço para nome XML a ser usado em XAML sistema autônomo elementos. Consulte Espaços de nomes XAML e mapeamentos de espaços de nomes.

Requisitos para uma classe personalizada como um elemento XAML

Para poder ser instanciada como um elemento de objeto, sua classe deve atender aos seguintes requisitos:

  • A classe personalizada deve ser pública e suportar um construtor público padrão (sem parâmetros). (Estruturas de código gerenciado implicitamente oferecem suporte a tal construtor.)

  • A classe personalizada não deve ser um classe aninhada (classes aninhadas e o "ponto" na sua sintaxe interferem com outros recursos WPF como as propriedades anexadas).

Além de ativar a sintaxe de elemento objeto, também se ativa a sintaxe do elemento propriedade para quaisquer outras propriedades públicas que levem o objeto como seus tipos de valor. Isso ocorre porque o objeto pode agora ser instanciado como um elemento de objeto e pode preencher o valor do elemento propriedade de tal propriedade.

Estruturas

Estruturas que você define sistema autônomo tipos personalizados são sempre capazes de ser construído no XAML em WPF .Isso é porque o CLR compiladores criar implicitamente um construtor padrão para uma estrutura que inicializa todos sistema autônomo valores de propriedade para seus padrões. Em alguns casos, o padrão construção comportamento e/ou objeto de elemento uso para uma estrutura não é desejável. Talvez a estrutura destina-se a valores de preenchimento e função conceitualmente sistema autônomo uma união, onde sistema autônomo valores contidos podem ter interpretações mutuamente exclusivas e, portanto, nenhuma de suas propriedades são configuráveis. A WPF exemplo dessa estrutura é GridLength. Em geral, essas estruturas devem implementar um conversor de tipos que os valores podem ser expressos em formulário atributo, usando convenções de seqüência que criar interpretações diferentes ou modos de valores da estrutura e a estrutura também devem expor comportamento semelhante para construção de código por meio de um construtor não-padrão.

Requisitos para as propriedades de uma classe personalizada como atributos XAML

Propriedades devem fazer referência a um tipo por valor (como uma primitiva), ou usar uma classe de tipo que tem um construtor padrão ou um dedicado conversor de tipos no nível de classe.

Como alternativa, a propriedade pode fazer referência a um tipo de classe abstrata, ou uma interface. Para classes abstratas ou interfaces, a expectativa em tempo de execução é que o valor da propriedade deve ser preenchido com instâncias de classe práticas que implementam a interface, ou instâncias de classe que derivam da classe abstrata.

Propriedades podem ser declaradas em uma classe abstrata, mas só podem ser definidas em práticas classes que derivam da classe abstrata, como criar o elemento de objeto para a classe em todos os exige um construtor padrão público na classe.

Sintaxe de atributo de conversor de tipo ativado

Se for fornecido um conversor de tipos atribuído e dedicado no nível de classe, a conversão de tipos aplicada permite a sintaxe de atributo para qualquer propriedade que precisa criar uma instância desse tipo. Um conversor de tipos não ativa o uso do tipo de elemento objeto; somente a presença de um construtor padrão para aquele tipo ativa o uso do elemento objeto. Portanto, as propriedades que são ativadas por conversor de tipo não são, de uma forma geral, utilizáveis em sintaxe de propriedade, a menos que o próprio tipo também ofereça suporte à sintaxe de elemento de objeto. A exceção a isso é que é possível especificar uma sintaxe do elemento propriedade, mas o elemento propriedade contém uma sequência de caracteres. Esse uso é realmente basicamente equivalente a um uso de sintaxe de atributo, e tal uso não é comum a menos que haja a necessidade de manuseio mais robusto de espaço em branco do valor do atributo. Por exemplo, a seguir está um uso de elemento propriedade que utiliza uma sequência de caracteres, e o uso de atributo equivalente:

<Button>Hallo!
  <Button.Language>
    de-DE
  </Button.Language>
</Button>
<Button Language="de-DE">Hallo!</Button>

Exemplos de propriedades onde a sintaxe de atributo é permitida mas a sintaxe do elemento propriedade que contém um elemento objeto não é permitida por XAML são várias propriedades que tomam o tipo Cursor. A classe Cursor tem um conversor de tipos dedicado CursorConverter, mas não expõe um construtor padrão, portanto, a propriedade Cursor somente pode ser definida pela sintaxe de atributo mesmo que o tipo Cursor seja um tipo de referência.

Conversores de tipo por Propriedade

Como alternativa, a propriedade em si pode declarar um conversor de tipos no nível de propriedade. Isso permite uma "minilinguagem" que instancia objetos do tipo da propriedade em linha, pelo processamento de entrada de valores de sequência de caracteres do atributo como entrada para uma operação ConvertFrom com base no tipo apropriado. Geralmente isso é feito para fornecer um acessador de conveniência, e não como os meios exclusivos para configurar uma propriedade em XAML. No entanto, também é possível usar conversores de tipo para atributos em que deseja usar tipos CLR existentes que não fornecem um construtor padrão ou um conversor de tipos atribuído. Exemplos de WPF APIs são determinadas propriedades que assumem o tipo CultureInfo. Nesse caso, WPF usou o tipo Microsoft .NET Framework CultureInfo existente para melhor endereçar situações de compatibilidade e migração que foram usados nas versões anteriores de estruturas, mas o tipo CultureInfo não oferecia suporte aos construtores necessários ou conversão de tipos type-level para ser usado como um valor da propriedade XAML diretamente.

Sempre que uma propriedade que tenha um uso XAML for exposta, especialmente se você for um autor de controle, considere fortemente suportar essa propriedade com uma propriedade de dependência. Isso é especialmente verdadeiro se a implementação Windows Presentation Foundation (WPF) existente do processador XAML for usada, porque é possível melhorar o desempenho usando o suporte DependencyProperty. Um propriedade de dependência irá expor recursos do sistema de propriedades para a propriedade que usuários virão a esperar de uma propriedade acessível XAML. Isso inclui recursos como animação, associação de dados e suporte a estilo. Para obter mais informações, consulte Propriedades de Dependência Personalizada e Carregando XAML e Propriedades de Dependência.

Escrevendo e Atribuindo um Conversor de Tipo

Frequentemente será necessário escrever uma classe derivada TypeConverter personalizada para fornecer conversão de tipo para seu tipo de propriedade. Para obter instruções sobre como criar e derivar-se de um conversor de tipos que possa dar suporte à usos XAML, e como aplicar o TypeConverterAttribute, consulte TypeConverters and XAML.

Requisitos para sintaxes de atributos de manipuladores de eventos XAML em eventos de uma classe personalizada

Para ser usado como um evento CLR, o evento deve ser exposto como um evento público em uma classe que suporta um construtor padrão, ou em uma classe abstrata onde o evento pode ser acessado em classes derivadas. Para poder ser usada convenientemente como um evento roteado, o evento CLR deve implementar add explícita e métodos remove que adicionam e removem manipuladores para a assinatura do evento CLR e encaminham esses manipuladores para o AddHandler e métodos RemoveHandler. Esses métodos adicionam ou removem os manipuladores para o armazenamento roteado do manipulador de eventos na instância à qual o evento está associado.

ObservaçãoObservação:

É possível registrar manipuladores para eventos roteados usando diretamente AddHandlere deliberadamente não definir um CLR evento que expõe o evento roteado. Isso geralmente não é recomendado porque o evento não permitirá sintaxe de atributo XAML para anexar manipuladores, e sua classe resultante oferecerá uma exibição XAML menos transparente do modelo de objeto de classe.

Escrevendo Propriedades de Coleção

Propriedades que assumem um tipo de coleção têm uma sintaxe XAML que permite especificar os objetos que são adicionados à coleção. Essa sintaxe possui dois recursos notáveis.

  • O objeto que é o objeto de coleção não precisa ser especificado na sintaxe de elemento do objeto. A presença desse tipo de coleção é implícita sempre que for especificada uma propriedade no XAML que utiliza um tipo de coleção.

  • Elementos filho da propriedade de coleção são processados para se tornar membros da coleção. Normalmente, o acesso ao código para os membros de uma coleção é realizado através de métodos de coleção, como Adicionar, ou por uma propriedade do indexador de coleção. Mas a sintaxe XAML não tem suporte para métodos ou indexadores. Coleções obviamente são um requisito muito comum para criar uma árvore de elementos, e é necessária alguma forma para preencher essas coleções numa XAML declarativa. Portanto, elementos filho de uma propriedade de coleção são processados adicionando-os à coleção que é o valor do tipo de propriedade da coleção.

O processador WPF XAML usa a seguinte definição para o que constitui uma propriedade de coleção. O tipo de propriedade da propriedade deve implementar um dos seguintes:

Cada um desses tipos tem um método Add, que é usado pelo processador XAML para adicionar itens à coleção subjacente.

ObservaçãoObservação:

O generic List and Dictionary interfaces (IList<T> and IDictionary<TKey, TValue>) are not supported for collection detection by the WPF XAML processor. No entanto, é possível usar a classe List<T> como uma classe base, pois ela implementa IList diretamente, ou Dictionary<TKey, TValue> como uma classe base, pois ela implementa IDictionary diretamente.

Ao declarar uma propriedade que utiliza uma coleção, tenha cuidado como o valor da propriedade é inicializado em novas instâncias do tipo. Se a propriedade não estiver sendo implemetada como uma propriedade de dependência, em seguida, fazer com que a propriedade use um campo de backup que chama o construtor de tipo de coleção é adequado. Se a propriedade for uma propriedade de dependência, então será necessário inicializar a propriedade de coleção como parte do construtor de tipo padrão. Isso ocorre porque uma propriedade de dependência leva seu valor padrão de metadados, e normalmente não se deseja que o valor inicial de uma propriedade de coleção seja uma coleção estática e compartilhada (deve haver uma instância de coleção por cada instância de tipo). Para obter mais informações, consulte Propriedades de Dependência Personalizada.

É possível implementar um tipo de coleção personalizada para a propriedade de coleção. Por causa do tratamento implícito da propriedade de coleção, o tipo de coleção personalizado não necessita fornecer um construtor padrão para ser usado em XAML implicitamente. No entanto, é possível, opcionalmente, fornecer um construtor padrão para o tipo de coleção. Isso pode ser uma prática que vale a pena, porque, a menos que se forneça um construtor padrão, não é possível declarar explicitamente a coleção como um elemento de objeto. Alguns autores de marcações podem preferir ver a coleção explícita como uma questão de estilo de marcação. Além disso, um construtor padrão pode simplificar os requisitos de inicialização ao criar novos objetos que usam o tipo de coleção como um valor da propriedade.

Declarando propriedades de conteúdo XAML

O idioma XAML define o conceito de uma propriedade de conteúdo XAML. Cada classe que é útil na sintaxe de objetos pode ter exatamente uma propriedade de conteúdo XAML. Para declarar uma propriedade para ser a propriedade de conteúdo XAML de sua classe, aplique o ContentPropertyAttribute como parte de definição de classe. Especifique o nome da propriedade de conteúdo pretendida XAML como o Name no atributo.

É possível especificar uma propriedade de coleção para ser a propriedade de conteúdo XAML. Isso resulta em um uso para essa propriedade pela qual o elemento de objeto pode ter um ou mais elementos filho, sem qualquer elementos de objeto de coleção intervenientes ou marcas de elemento de propriedade . Esses elementos são, em seguida, tratados como o valor para a propriedade de conteúdo XAML e são adicionados à instância de coleção de backup.

Algumas propriedades de conteúdo WPF XAML existentes usam o tipo de propriedade de Object. Isso permite uma propriedade de conteúdo XAML que possa levar valores primitivos, como um String, bem como levar um valor de objeto de referência único. Se for seguir esse modelo, seu tipo é responsável por determinação de tipo, bem como por manipulação de tipos possíveis. A razão típica para um modelo de tipo Object é oferecer suporte tanto a um meio simples de adicionar conteúdo de objeto como uma sequência de caracteres (que recebe um tratamento de apresentação padrão), quanto a um meio avançado de adicionar conteúdo de objeto que especifique uma apresentação não padrão.

Serializando XAML

Para alguns cenários, como se você fosse um autor de controle, é possível também que deseje garantir que qualquer representação de objeto que possa ser instanciada no XAML também possa ser serializada de volta para XAML equivalente. Requisitos de serialização não são descritos neste tópico. Consulte Visão geral sobre criação de controles e Árvore de Elemento e Serialização.

Consulte também

Conceitos

XAML Overview

Propriedades de Dependência Personalizada

Visão geral sobre criação de controles

Visão geral sobre elementos base

Carregando XAML e Propriedades de Dependência