Partilhar via


Visão geral dos conversores de tipo para XAML

Os conversores de tipo fornecem lógica para um gravador de objetos que converte de uma cadeia de caracteres na marcação XAML em objetos específicos em um gráfico de objetos. Nos Serviços XAML .NET, o conversor de tipo deve ser uma classe que deriva de TypeConverter. Alguns conversores também suportam o caminho de guarda XAML e podem ser usados para serializar um objeto em forma de cadeia de caracteres na marcação para serialização. Este tópico descreve como e quando os conversores de tipo em XAML são acionados e fornece conselhos de implementação para as substituições de método de TypeConverter.

Conceitos de conversão de tipo

As seções a seguir explicam conceitos básicos sobre como o XAML usa cadeias de caracteres e como os gravadores de objetos nos Serviços XAML .NET usam conversores de tipo para processar alguns dos valores de cadeia de caracteres encontrados em uma fonte XAML.

XAML e Valores de Cadeia de Caracteres

Quando você define um valor de atributo em um arquivo XAML, o tipo inicial desse valor é uma cadeia de caracteres em um sentido geral e um valor de atributo de cadeia de caracteres em um sentido XML. Mesmo outras primitivas, como Double são inicialmente cadeias de caracteres para um processador XAML.

Na maioria dos casos, um processador XAML precisa de duas informações para processar um valor de atributo. A primeira informação é o tipo de valor da propriedade que está sendo definida. Qualquer cadeia de caracteres que defina um valor de atributo e que seja processada em XAML deve ser convertida ou resolvida para um valor desse tipo. Se o valor for uma primitiva compreendida pelo analisador XAML (como um valor numérico), uma conversão direta da cadeia de caracteres será tentada. Se o valor do atributo fizer referência a uma enumeração, a cadeia de caracteres fornecida será verificada quanto a uma correspondência de nome com uma constante nomeada nessa enumeração. Se o valor não for uma primitiva compreendida pelo analisador ou um nome constante de uma enumeração, o tipo aplicável deverá ser capaz de fornecer um valor ou referência baseado em uma cadeia de caracteres convertida.

Observação

As diretivas de linguagem XAML não usam conversores de tipo.

Conversores de tipo e extensões de marcação

Os usos da extensão de marcação devem ser manipulados por um processador XAML antes que ele verifique o tipo de propriedade e outras considerações. Por exemplo, se uma propriedade definida como um atributo normalmente tem uma conversão de tipo, mas em um caso específico é definida pelo uso de uma extensão de marcação, então processa primeiro o comportamento da extensão de marcação. Uma situação comum em que uma extensão de marcação é necessária é fazer uma referência a um objeto que já existe. Para esse cenário, um conversor de tipo sem estado só pode gerar uma nova instância, o que pode não ser desejável. Para obter mais informações sobre extensões de marcação, consulte Visão geral das extensões de marcação para XAML.

Conversores de tipo nativo

Nas implementações de serviços Windows Presentation Foundation (WPF) e .NET XAML, há certos tipos de CLR que têm manipulação de conversão de tipo nativa. No entanto, esses tipos de CLR não são convencionalmente pensados como primitivos. Um exemplo desse tipo é DateTime. Uma razão para isso é como a arquitetura do .NET Framework funciona: o tipo DateTime é definido em mscorlib, a biblioteca mais básica do .NET. DateTime não está permitido que seja atribuído por um atributo oriundo de um assembly externo que introduz uma dependência (TypeConverterAttribute é de System). Portanto, o mecanismo usual de descoberta do conversor de tipo por atribuição não pode ser suportado. Em vez disso, o analisador XAML tem uma lista de tipos que precisam de processamento nativo e processa esses tipos de forma semelhante à forma como as primitivas verdadeiras são processadas. No caso de DateTime, este processamento envolve uma chamada para Parse.

Implementando um conversor de tipo

As seções a seguir discutem a API da classe TypeConverter.

Conversor de Tipos

Em Serviços XAML .NET, todos os conversores de tipo usados para fins XAML são classes que derivam da classe base TypeConverter. A classe TypeConverter existia em versões do .NET Framework antes do XAML existir; Um dos cenários TypeConverter originais era fornecer conversão de cadeia de caracteres para editores de propriedades em Visual Designers.

Para XAML, a função de TypeConverter é expandida. Para fins de XAML, TypeConverter é a classe base para fornecer suporte para determinadas conversões to-string e from-string. From-string permite analisar um valor de atributo string de XAML. O método "to-string" pode permitir o processamento de um valor de tempo de execução de uma propriedade específica de objeto de volta num atributo em XAML para serialização.

TypeConverter define quatro membros que são relevantes para conversão em string e from-string para fins de processamento XAML:

Desses membros, o método mais importante é ConvertFrom, que converte a cadeia de caracteres de entrada para o tipo de objeto necessário. O método ConvertFrom pode ser implementado para converter uma gama mais ampla de tipos no tipo de destino pretendido do conversor. Portanto, ele pode servir a propósitos que vão além do XAML, como dar suporte a conversões em tempo de execução. No entanto, para uso em XAML, somente o caminho de código que pode processar uma entrada de String é importante.

O segundo método mais importante é ConvertTo. Se um aplicativo for convertido em uma representação de marcação (por exemplo, se for salvo em XAML como um arquivo), ConvertTo estará envolvido no cenário maior de um gravador de texto XAML para produzir uma representação de marcação. Nesse caso, o caminho de código importante para XAML ocorre quando o chamador passa o parâmetro destinationType como String.

CanConvertTo e CanConvertFrom são métodos de suporte usados quando um serviço consulta os recursos da implementação TypeConverter. Você deve implementar esses métodos para retornar true para casos específicos de tipo que os métodos de conversão equivalentes do seu conversor suportam. Para fins de XAML, isso geralmente significa o tipo String.

Informações de cultura e conversores de tipo para XAML

Cada implementação TypeConverter pode interpretar exclusivamente o que é uma cadeia de caracteres válida para uma conversão e também pode usar ou ignorar a descrição do tipo que é passada como parâmetros. Uma consideração importante para cultura e conversão de tipo XAML é a seguinte: embora o uso de cadeias de caracteres localizáveis como valores de atributo seja suportado por XAML, você não pode usar essas cadeias de caracteres localizáveis como entrada de conversor de tipo com requisitos específicos de cultura. Essa limitação ocorre porque os conversores de tipo para valores de atributo XAML envolvem um comportamento de processamento XAML de linguagem fixa necessariamente que usa cultura en-US. Para obter mais informações sobre os motivos de design para essa restrição, consulte a especificação de linguagem XAML ([MS-XAML]) ou Visão geral da globalização e localização do WPF.

Como um exemplo onde a cultura pode ser um problema, algumas culturas usam uma vírgula em vez de um ponto como o delimitador de ponto decimal para números em forma de cadeia de caracteres. Esse uso colide com o comportamento que muitos conversores de tipo existentes têm, que é usar uma vírgula como delimitador. Passar uma cultura por xml:lang no XAML circundante não resolve o problema.

Implementando o ConvertFrom

Para ser utilizável como uma implementação TypeConverter que ofereça suporte a XAML, o método ConvertFrom para esse conversor deve aceitar uma cadeia de caracteres como o parâmetro value. Se a cadeia de caracteres estiver em um formato válido e puder ser convertida pela implementação TypeConverter, o objeto retornado deverá oferecer suporte a uma conversão para o tipo esperado pela propriedade. Caso contrário, a implementação ConvertFrom deve retornar null.

Cada implementação TypeConverter pode interpretar exclusivamente o que constitui uma cadeia de caracteres válida para uma conversão e também pode usar ou ignorar a descrição do tipo ou os contextos de cultura que são passados como parâmetros. No entanto, o processamento WPF XAML pode não passar valores para o contexto de descrição de tipo em todos os casos e também pode não passar cultura com base em xml:lang.

Observação

Não use as chaves ({}), especificamente a chave de abertura ({), como um elemento do formato da sua cadeia de caracteres. Esses caracteres são reservados como entrada e saída para uma sequência de extensão de marcação.

É apropriado lançar uma exceção quando o seu conversor de tipos precisa acessar um serviço XAML do escritor de objetos dos Serviços XAML do .NET, mas a chamada GetService feita no contexto não retorna esse serviço.

Implementar ConvertTo

ConvertTo é potencialmente usado para suporte à serialização. O suporte à serialização por meio ConvertTo para seu tipo personalizado e seu conversor de tipo não é um requisito absoluto. No entanto, se você estiver implementando um controle ou usando a serialização de como parte dos recursos ou design de sua classe, você deve implementar ConvertTo.

Para ser utilizável como uma implementação TypeConverter que ofereça suporte a XAML, o método ConvertTo para esse conversor deve aceitar uma instância do tipo (ou um valor) que é suportada como o parâmetro value. Quando o parâmetro destinationType é do tipo String, o objeto retornado deve poder ser convertido como String. A cadeia de caracteres retornada deve representar um valor serializado de value. Idealmente, o formato de serialização escolhido deve ser capaz de gerar o mesmo valor como se essa cadeia de caracteres fosse passada para a implementação ConvertFrom do mesmo conversor, sem perda significativa de informações.

Se o valor não puder ser serializado ou o conversor não oferecer suporte à serialização, a implementação ConvertTo deverá retornar null e poderá gerar uma exceção. No entanto, se você lançar exceções, deverá relatar a incapacidade de usar essa conversão como parte de sua implementação de CanConvertTo para que a prática recomendada de verificar com CanConvertTo primeiro para evitar exceções seja suportada.

Se o parâmetro destinationType não for do tipo String, você pode escolher seu próprio manuseio do conversor. Normalmente, volta para o tratamento da implementação base, que na base ConvertTo levanta uma exceção específica.

É apropriado lançar uma exceção quando o conversor de tipo deve ter acesso a um serviço XAML do gravador de objetos dos Serviços XAML .NET, mas a chamada GetService feita no contexto não devolve esse serviço.

Implementação de CanConvertFrom

A sua implementação CanConvertFrom deve retornar true para sourceType do tipo String e, caso contrário, recorrer à implementação base. Não lance exceções de CanConvertFrom.

Implementando CanConvertTo

A implementação CanConvertTo deve retornar true para destinationType do tipo Stringe, caso contrário, reverter para a implementação base. Não lance exceções de CanConvertTo.

Aplicando o atributo TypeConverterAttribute

Para que seu conversor de tipo personalizado seja usado como o conversor de tipo de atuação para uma classe personalizada pelos Serviços XAML do .NET, você deve aplicar o TypeConverterAttribute à sua definição de classe. O ConverterTypeName especificado através do atributo deve ser o nome do tipo do seu conversor de tipo personalizado. Se você aplicar esse atributo, quando um processador XAML manipular valores em que o tipo de propriedade usa seu tipo de classe personalizado, ele poderá inserir cadeias de caracteres e retornar instâncias de objeto.

Você também pode fornecer um conversor de tipo para cada propriedade. Em vez de aplicar um TypeConverterAttribute à definição de classe, aplique-o a uma definição de propriedade (a definição principal, não as implementações get/set dentro dela). O tipo da propriedade deve corresponder ao tipo que é processado pelo seu conversor de tipo personalizado. Com esse atributo aplicado, quando um processador XAML manipula valores dessa propriedade, ele pode processar cadeias de caracteres de entrada e retornar instâncias de objeto. A técnica do conversor por tipo de propriedade é útil se optar por utilizar um tipo de propriedade do Microsoft .NET Framework ou de outra biblioteca em que não possa controlar a definição da classe e não possa aplicar um TypeConverterAttribute lá.

Para fornecer um comportamento de conversão de tipo para um membro anexado personalizado, aplique TypeConverterAttribute ao método de acessador Get do padrão de implementação para o membro anexado.

Acesso ao contexto do provedor de serviços a partir de uma implementação de extensão de marcação

Os serviços disponíveis são os mesmos para qualquer conversor de valor. A diferença está em como cada conversor de valor recebe o contexto de serviço. No tópico Conversores de Tipo e Extensões de Marcação para XAML, está documentado como acessar os serviços e quais serviços estão disponíveis.

Convertidores de tipo no Fluxo de Nós XAML

Se estiver a trabalhar com um fluxo de nós XAML, a ação ou o resultado final de um conversor de tipo não foi ainda executada. Em um caminho de carregamento, a cadeia de caracteres de atributo que eventualmente precisa ser convertida de tipo para ser carregada permanece como um valor de texto entre um membro inicial e um membro final. O conversor de tipo eventualmente necessário para esta operação pode ser determinado usando a propriedade XamlMember.TypeConverter. No entanto, a obtenção de um valor válido de XamlMember.TypeConverter depende de ter um contexto de esquema XAML, que pode acessar essas informações por meio do membro subjacente ou do tipo de valor de objeto que o membro usa. Invocar o comportamento de conversão de tipo também requer o contexto de esquema XAML porque isso requer mapeamento de tipo e a criação de uma instância de conversor.

Ver também