Visão geral dos conversores de tipo para XAML
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 grafo de objetos. Nos Serviços XAML do .NET, o conversor de tipos deve ser uma classe derivada de TypeConverter. Alguns conversores também dão suporte ao caminho de salvamento XAML e podem ser usados para serializar um objeto em um formulário de cadeia de caracteres na marcação de serialização. Este tópico descreve como e quando conversores de tipo no XAML são invocados e fornece conselhos de implementação para as substituições de método de TypeConverter.
Conceitos de conversão de tipos
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 do .NET usam conversores de tipo para processar alguns dos valores de cadeia de caracteres encontrados em uma origem 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 outros primitivos, 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 parte das informações é 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, em última análise, ser convertida ou resolvida em um valor desse tipo. Se o valor for um primitivo compreendido 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 para que um nome corresponda a uma constante nomeada nessa enumeração. Se o valor não for um primitivo compreendido 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.
Nota
As diretivas de linguagem XAML não usam conversores de tipo.
Conversores de tipo e extensões de marcação
O uso de extensões de marcação precisa ser tratado por um processador XAML antes de verificar o tipo de propriedade e outras considerações. Por exemplo, se uma propriedade é definida como um atributo que normalmente passa por uma conversão de tipo, mas em um caso específico é definida por meio de uma extensão de marcação, então o comportamento da extensão de marcação é processado primeiro. 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 Extensões de Marcação para Visão Geral de XAML.
Conversores de tipos nativos
Nas implementações de serviços do WPF (Windows Presentation Foundation) e do .NET XAML, há determinados tipos CLR que têm tratamento de conversão de tipo nativo. No entanto, esses tipos CLR não são considerados convencionalmente como primitivos. Um exemplo desse tipo é DateTime. Um motivo para isso é como a arquitetura do .NET Framework funciona: o tipo DateTime é definido no mscorlib, a biblioteca mais básica do .NET. DateTime não pode receber um atributo que venha de outro assembly que introduza uma dependência (TypeConverterAttribute é do System). Portanto, não há suporte para o mecanismo de descoberta de conversor de tipo usual por meio da atribuição. Em vez disso, o analisador XAML tem uma lista de tipos que precisam de processamento nativo e processa esses tipos semelhantes à forma como os primitivos verdadeiros são processados. No caso de DateTime, esse processamento envolve uma chamada para Parse.
Implementando um conversor de tipo
As seções a seguir discutem a API da classe TypeConverter.
TypeConverter
Nos Serviços XAML do .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 de TypeConverter originais era fornecer conversão de cadeia de caracteres para editores de propriedades em designers visuais.
Para XAML, a função de TypeConverter é expandida. Para fins de XAML, TypeConverter é a classe base para fornecer suporte para certas conversões para string e de string. Converter de string permite analisar sintaticamente um valor de atributo de cadeia de caracteres a partir de XAML. Converter para string pode permitir o processamento do valor em tempo de execução de uma propriedade de objeto específico, revertendo-o como um atributo no XAML para serialização.
TypeConverter define quatro membros que são relevantes para converter para cadeia de caracteres e de cadeia de caracteres para fins de processamento XAML:
Desses membros, o método mais importante é ConvertFrom, que converte a cadeia de caracteres de entrada no tipo de objeto necessário. O método ConvertFrom pode ser implementado para converter um intervalo maior de tipos no tipo de destino pretendido do conversor. Portanto, ele pode servir a finalidades que se estendem além do XAML, como dar suporte a conversões em tempo de execução. No entanto, para uso XAML, somente o caminho de código que pode processar uma entrada String é importante.
O segundo método mais importante é ConvertTo. Se um aplicativo for convertido em uma representação de marcação (por exemplo, se ele 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 é quando o chamador passa um destinationType
para String.
CanConvertTo e CanConvertFrom são métodos de suporte usados quando um serviço consulta os recursos da implementação do TypeConverter. Esses métodos devem ser implementados para retornar o true
para casos específicos de tipo aos quais os métodos de conversão equivalentes do seu conversor dão suporte. Para fins XAML, isso geralmente significa o tipo String.
Informações de cultura e conversores de tipos 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 a cultura e a conversão de tipo XAML é a seguinte: embora o uso de cadeias de caracteres localizáveis como valores de atributo seja compatível com XAML, você não pode usar essas cadeias de caracteres localizáveis como entrada de conversor de tipo com requisitos de cultura específicos. Essa limitação ocorre porque conversores de tipo para valores de atributo XAML envolvem um comportamento de processamento XAML de linguagem necessariamente fixa que utiliza a cultura en-US
. Para obter mais informações sobre os motivos de design para essa restrição, consulte a especificação da linguagem XAML ([MS-XAML]) ou visão geral de globalização e localização do WPF.
Como um exemplo em que a cultura pode ser um problema, algumas culturas usam uma vírgula em vez de um período como delimitador de ponto decimal para números na 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 ConvertFrom
Para ser utilizável como uma implementação TypeConverter que dá 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á dar suporte a uma conversão para o tipo esperado pela propriedade. Caso contrário, a implementação do 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 de XAML do WPF não pode passar valores para o contexto de descrição de tipo em todos os casos; tampouco consegue passar a cultura com base no xml:lang
.
Nota
Não use as chaves ({}), especificamente a chave de abertura ({), como elemento de formatação de cadeias 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 conversor de tipo precisa ter acesso a um serviço XAML do escritor de objetos do .NET XAML Services, mas a chamada GetService feita no contexto não retorna esse serviço.
Implementando ConvertTo
ConvertTo é potencialmente usado para suporte à serialização. O suporte à serialização por meio do ConvertTo para o tipo personalizado e seu conversor de tipo não é uma exigência absoluta. No entanto, se você estiver implementando um controle ou usando a serialização como parte dos recursos ou design de sua classe, deverá implementar ConvertTo.
Para ser utilizável como uma implementação de TypeConverter que dá suporte a XAML, o método ConvertTo para esse conversor deve aceitar uma instância do tipo (ou um valor) com suporte como o parâmetro value
. Quando o parâmetro destinationType
é do tipo String, o objeto retornado deve ser capaz de 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 que 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 der suporte à serialização, a implementação do ConvertTo deverá retornar null
e pode gerar uma exceção. No entanto, se você lançar exceções, deverá relatar a impossibilidade de usar essa conversão como parte de sua implementação de CanConvertTo, de modo que a prática recomendada de verificar primeiro com CanConvertTo para evitar exceções seja suportada.
Se o parâmetro destinationType
não for do tipo String, você poderá escolher sua própria manipulação de conversor. Normalmente, você retorna para a implementação padrão, na qual a base ConvertTo gera uma exceção específica.
É apropriado lançar uma exceção quando o conversor de tipo precisa ter acesso a um serviço XAML do escritor de objetos do .NET XAML Services, mas a chamada GetService feita no contexto não retorna esse serviço.
Implementando CanConvertFrom
Sua implementação de CanConvertFrom deve retornar true
para sourceType
do tipo String e, caso contrário, recorrer à implementação base. Não gere exceções de CanConvertFrom.
Implementando CanConvertTo
A sua implementação de CanConvertTo deve retornar true
para destinationType
do tipo String e, caso contrário, recorrer à implementação base. Não gere exceções de CanConvertTo.
Aplicando o TypeConverterAttribute
Para que o conversor de tipo personalizado seja usado como 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 que você especificar através do atributo precisa ser o nome do tipo do seu conversor de tipo customizado. Se você aplicar esse atributo, quando um processador XAML manipula valores em que o tipo de propriedade usa seu tipo de classe personalizado, ele pode 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 de get
/set
dentro dela). O tipo da propriedade deve corresponder ao tipo processado pelo 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 de conversor de tipo por propriedade é útil se você optar por usar um tipo de propriedade do Microsoft .NET Framework ou de alguma outra biblioteca em que não é possível controlar a definição de classe e não pode aplicar uma TypeConverterAttribute lá.
Para fornecer um comportamento de conversão de tipo para um membro anexado personalizado, aplique TypeConverterAttribute ao método Get
acessador do padrão de implementação para o membro anexado.
Acessar o contexto do provedor de serviços 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. Os serviços de acesso e os disponíveis estão documentados no tópico Conversores de Tipo e Extensões de Marcação para XAML.
Conversores de tipo no fluxo de nós XAML
Se você está trabalhando com um fluxo de nó XAML, a ação ou o resultado final de um conversor de tipo ainda não foi executada. Em um caminho de carregamento, a cadeia de caracteres de atributo que eventualmente precisa ser convertida para o tipo necessário para o carregamento permanece como um valor de texto dentro do membro inicial e do membro final. O conversor de tipo que eventualmente é necessário para essa operação pode ser determinado usando a propriedade XamlMember.TypeConverter. No entanto, obter 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 do 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 criação de uma instância de conversor.
Consulte também
.NET Desktop feedback