Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
As extensões de marcação são uma técnica XAML para obter um valor que não seja um tipo XAML primitivo ou específico. Para uso de atributo, as extensões de marcação utilizam a conhecida sequência de caracteres de uma chave {
de abertura para inserir o escopo da extensão de marcação e uma chave }
de fechamento para sair. Ao usar os Serviços XAML do .NET, você pode usar algumas das extensões de marcação de linguagem XAML predefinidas do assembly System.Xaml. Você também pode subclassificar a classe MarkupExtension, definida em System.Xaml e, assim, definir suas próprias extensões de marcação. Ou você pode usar extensões de marcação definidas por uma estrutura específica se já estiver fazendo referência a essa estrutura.
Quando um uso de extensão de marcação é acessado, o gravador de objetos XAML pode fornecer serviços a uma classe personalizada MarkupExtension por meio de um ponto de conexão de serviço na MarkupExtension.ProvideValue substituição. Os serviços podem ser usados para obter contexto sobre o uso, funcionalidades específicas do gravador de objetos, contexto de esquema XAML e assim por diante.
Extensões de marcação definidas por XAML
Várias extensões de marcação são implementadas pelos Serviços XAML do .NET para suporte à linguagem XAML. Essas extensões de marcação correspondem a partes da especificação de XAML como um idioma. Normalmente, eles são identificáveis pelo x:
prefixo na sintaxe, conforme visto em uso comum. As implementações dos Serviços XAML do .NET para esses elementos de linguagem XAML derivam da MarkupExtension classe base.
Observação
O prefixo x:
é usado no mapeamento típico do namespace da linguagem XAML, no elemento raiz de uma produção XAML. Por exemplo, o projeto do Visual Studio e os modelos de página para várias estruturas específicas iniciam um arquivo XAML usando esse x:
mapeamento. Você pode escolher um token de prefixo diferente em seu próprio mapeamento de namespace XAML, mas essa documentação assumirá o mapeamento padrão x:
como um meio de identificar as entidades que são uma parte definida do namespace XAML da linguagem XAML, em oposição ao namespace XAML padrão de uma estrutura específica ou a outros namespaces CLR ou XML arbitrários.
x:Type
x:Type
fornece o Type objeto para o tipo nomeado. Essa funcionalidade é usada com mais frequência em mecanismos de adiamento que utilizam o tipo CLR subjacente e a derivação de tipo como um apelido ou identificador de agrupamento. Estilos e modelos do WPF e seu uso de TargetType
propriedades são um exemplo específico. Para obter mais informações, consulte x:Type Markup Extension.
x:Static
x:Static
produz valores estáticos a partir de entidades de código do tipo valor, que não são diretamente do tipo de valor de uma propriedade, mas que podem ser avaliados para esse tipo. Isso é útil para especificar valores que já existem como constantes conhecidas em uma definição de tipo. Para obter mais informações, consulte x:Static Markup Extension.
x:Null
x:Null
especifica null
como um valor para um membro XAML. Dependendo do design de tipos específicos ou de conceitos de estrutura maiores, null
nem sempre é um valor padrão para uma propriedade ou o valor implícito de um atributo de cadeia de caracteres vazio. Para obter mais informações, consulte x:Null Markup Extension.
x:Array
x:Array
dá suporte à criação de matrizes gerais na sintaxe XAML nos casos em que o suporte à coleção fornecido por elementos base e modelos de controle não é usado deliberadamente. Para obter mais informações, consulte x:Array Markup Extension. Especificamente no XAML 2009, as matrizes são acessadas como primitivas de linguagem em vez de como uma extensão. Para obter mais informações, consulte recursos de linguagem XAML 2009.
x:Reference
x:Reference
faz parte do XAML 2009, uma extensão do conjunto de idiomas original (2006).
x:Reference
representa uma referência a outro objeto existente em um grafo de objeto. Esse objeto é identificado por sua x:Name
. Para obter mais informações, consulte x:Reference Markup Extension.
Outros x: Estruturas
Existem outros x:
constructos para dar suporte a recursos de linguagem XAML, mas eles não são implementados como extensões de marcação. Para obter mais informações, consulte recursos de linguagem XAML (x:).
A classe base de MarkupExtension
Para definir uma extensão de marcação personalizada que pode interagir com as implementações padrão de leitores XAML e gravadores XAML no System.Xaml, você deriva uma classe da classe abstrata MarkupExtension . Essa classe tem um método para substituir, que é ProvideValue. Talvez você também precise definir construtores adicionais para dar suporte a argumentos ao uso da extensão de marcação e às propriedades configuráveis correspondentes.
Por meio ProvideValue, uma extensão de marcação personalizada tem acesso a um contexto de serviço que descreve o ambiente em que a extensão de marcação é invocada por um processador XAML. No caminho de carga, isso normalmente é um XamlObjectWriter. No caminho de salvamento de arquivo, isso normalmente é um XamlXmlWriter. Cada relatório apresenta o contexto do serviço como uma classe interna de contexto do provedor de serviços XAML que segue um modelo de provedor de serviços. Para obter mais informações sobre os serviços disponíveis e o que eles representam, consulte Conversores de Tipo e Extensões de Marcação para XAML.
Sua classe de extensão de marcação deve usar um nível de acesso público; os processadores XAML sempre devem ser capazes de instanciar a classe de suporte da extensão de marcação para usar seus serviços.
Definindo o tipo de suporte para uma extensão de marcação personalizada
Ao usar os Serviços XAML do .NET ou estruturas que se baseiam nos Serviços XAML do .NET, você tem duas opções para nomear o tipo de suporte de extensão de marcação. O nome do tipo é relevante para como os gravadores de objetos XAML tentam acessar e invocar um tipo de suporte de extensão de marcação quando encontram um uso de extensão de marcação no XAML. Use uma das seguintes estratégias de nomenclatura:
- Nomeie o tipo de maneira que seja uma combinação exata com o token de uso de marcação XAML. Por exemplo, para dar suporte a um uso de extensão
{Collate ...}
, nomeie o tipo de suporteCollate
. - Nomeie o nome do tipo como o token de cadeia de caracteres de uso mais o sufixo
Extension
. Por exemplo, para dar suporte a um uso de extensão{Collate ...}
, nomeie o tipo de suporteCollateExtension
.
A ordem de pesquisa é procurar primeiro o nome da classe com o sufixo Extension
e, em seguida, procurar o nome da classe sem o sufixo Extension
.
Da perspectiva de uso da marcação, a inclusão do Extension
sufixo como parte do uso é válida. No entanto, isso se comporta como se Extension
fosse realmente parte do nome da classe, e os gravadores de objetos XAML falhariam em resolver uma classe de suporte de extensão de marcação XAML para esse uso se a classe de suporte não tivesse o sufixo Extension
.
O construtor sem parâmetros
Para todos os tipos de suporte à extensão de marcação, você deve expor um construtor público sem parâmetros. Um construtor sem parâmetros é necessário para qualquer caso em que um escritor de objetos XAML instancia a extensão de marcação a partir de um elemento de objeto. O suporte ao uso de elementos de objeto é uma expectativa justa para uma extensão de marcação, especialmente para serialização. No entanto, você pode implementar uma extensão de marcação sem um construtor público se pretender dar suporte apenas aos usos de atributo da extensão de marcação.
Se o uso da extensão de marcação não tiver argumentos, o construtor sem parâmetros será necessário para dar suporte ao uso.
Padrões de construtor e argumentos posicionais para uma extensão de marcação personalizada
Para uma extensão de marcação com uso de argumento pretendido, os construtores públicos devem corresponder aos modos de uso pretendido. Em outras palavras, se a extensão de marcação for projetada para exigir um argumento posicional como um uso válido, você deverá dar suporte a um construtor público com um parâmetro de entrada que usa o argumento posicional.
Por exemplo, suponha que a Collate
extensão de marcação seja destinada a dar suporte apenas a um modo em que haja um argumento posicional que represente seu modo, especificado como uma CollationMode
constante de enumeração. Nesse caso, deve haver um construtor com o seguinte formulário:
public Collate(CollationMode collationMode) {...}
Em um nível básico, os argumentos passados para uma extensão de marcação são uma cadeia de caracteres porque estão sendo encaminhados dos valores de atributo da marcação. Você pode fazer todos os seus argumentos strings e manipular entradas nesse nível. No entanto, você tem acesso a determinado processamento que ocorre antes que os argumentos de extensão de marcação sejam passados para a classe de suporte.
O processamento funciona conceitualmente como se a extensão de marcação fosse um objeto a ser criado e, em seguida, seus valores de membro são definidos. Cada propriedade especificada a ser definida é avaliada de forma semelhante a como um membro especificado pode ser definido em um objeto criado quando XAML é analisado. Há duas diferenças importantes:
- Conforme observado anteriormente, um tipo de suporte para extensão de marcação não precisa ter um construtor sem parâmetros para ser instanciado no XAML. Sua construção de objeto é adiada até que seus possíveis argumentos na sintaxe de texto sejam tokenizados e avaliados como argumentos posicionais ou nomeados, e o construtor apropriado seja chamado nesse momento.
- As utilizações de extensões de marcação podem ser aninhadas. A extensão de marcação mais interna é avaliada primeiro. Portanto, você pode assumir esse uso e declarar um dos parâmetros de construção como um tipo que requer um conversor de valor (como uma extensão de marcação) para produzir.
Uma dependência desse processamento foi mostrada no exemplo anterior. O gravador de objetos XAML dos Serviços XAML do .NET transforma os nomes de constantes em valores de enumeração no nível nativo.
A sintaxe de texto no processamento de um parâmetro posicional de extensão de marcação também pode depender de um conversor de tipo que está associado ao tipo no argumento de construção.
Os argumentos são chamados de argumentos posicionais porque a ordem na qual os tokens no uso são encontrados corresponde à ordem posicional do parâmetro de construtor ao qual eles são atribuídos. Por exemplo, considere a seguinte assinatura de construtor:
public Collate(CollationMode collationMode, object collateThis) {...}
Um processador XAML espera dois argumentos posicionais para essa extensão de marcação. Se houver um uso {Collate AlphaUp,{x:Reference circularFile}}
, o AlphaUp
token será enviado para o primeiro parâmetro e avaliado como uma CollationMode
enumeração nomeada constante. O resultado da parte interna x:Reference
é enviado para o segundo parâmetro e avaliado como um objeto.
Nas regras especificadas de XAML para sintaxe de extensão de marcação e processamento, a vírgula é o delimitador entre argumentos, sejam eles argumentos posicionais ou argumentos nomeados.
Aridade duplicada de argumentos posicionais
Se um gravador de objetos XAML encontrar um uso de extensão de marcação com argumentos posicionais e houver vários argumentos de construtor que assumem esse número de argumentos (uma aridade duplicada), isso não necessariamente constitui um erro. O comportamento depende de uma configuração de contexto de esquema XAML personalizável. SupportMarkupExtensionsWithDuplicateArity Se SupportMarkupExtensionsWithDuplicateArity for true
, um gravador de objeto XAML não deve gerar uma exceção apenas por motivos de aridade duplicada. O comportamento além desse ponto não é estritamente definido. A premissa básica do design é que o contexto do esquema tenha informações de tipo disponíveis para os parâmetros específicos e possa tentar conversões explícitas que correspondam aos candidatos duplicados para identificar qual assinatura pode ser a melhor correspondência. Uma exceção ainda poderá ser gerada se nenhuma assinatura puder passar nos testes impostos por esse contexto de esquema específico que está em execução em um gravador de objeto XAML.
Por padrão, SupportMarkupExtensionsWithDuplicateArity está false
no XamlSchemaContext baseado no CLR para serviços XAML de .NET. Assim, o padrão XamlObjectWriter gera exceções se encontrar um uso de extensão de marcação em que há aridade duplicada nos construtores do tipo de backup.
Argumentos nomeados para uma extensão de marcação personalizada
As extensões de marcação, conforme especificado pelo XAML, também podem usar um formulário de argumentos nomeados para uso. No primeiro nível de tokenização, a sintaxe de texto é dividida em argumentos. A presença de um sinal de igual (=) dentro de qualquer argumento identifica um argumento como um argumento nomeado. Esse argumento também é tokenizado em um par nome/valor. Nesse caso, o nome designa uma propriedade pública ajustável do tipo de suporte da extensão de marcação. Se você pretende dar suporte ao uso de argumento nomeado, você deve fornecer essas propriedades configuráveis públicas. As propriedades podem ser herdadas desde que permaneçam públicas.
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.
Uso do elemento de propriedade em uma extensão de marcação
Os cenários para usos de extensão de marcação geralmente são projetados em torno do uso da extensão de marcação no uso de atributo. No entanto, também é possível definir a classe de backup para dar suporte ao uso do elemento de propriedade.
Para dar suporte ao uso do elemento de propriedade na sua extensão de marcação, defina um construtor público sem parâmetros. Esse deve ser um construtor de instância, não um construtor estático. Isso é necessário porque um processador XAML geralmente deve invocar o construtor sem parâmetros em qualquer elemento de objeto que ele processe a partir do código XAML, e isso inclui classes de extensão de marcação como elementos de objeto. Para cenários avançados, você pode definir caminhos de construção não padrão para classes. (Para obter mais informações, consulte x:FactoryMethod Directive.) No entanto, você não deve usar esses padrões para fins de extensão de marcação porque isso torna a descoberta do padrão de uso muito mais difícil, tanto para designers quanto para usuários de marcação bruta.
Atribuição de uma extensão de marcação personalizada
Para dar suporte a ambientes de design e determinados cenários de gravador de objetos XAML, você deve atribuir um tipo de suporte à extensão de marcação com vários atributos CLR. Esses atributos relatam o uso da extensão de marcação pretendida.
MarkupExtensionReturnTypeAttribute relata as Type informações do tipo de objeto que ProvideValue retorna. Por sua assinatura pura, ProvideValue retorna Object. No entanto, muitos consumidores podem desejar informações mais detalhadas sobre o tipo de retorno. Isso inclui:
- Designers e IDEs, que potencialmente podem fornecer suporte com reconhecimento de tipo para utilização de extensões de marcação.
- Implementações avançadas de
SetMarkupExtension
manipuladores em classes de destino, que podem depender da reflexão para determinar o tipo de retorno de uma extensão de marcação em vez de ramificar em implementações conhecidas MarkupExtension específicas por nome.
Serialização das aplicações de extensões de marcações
Quando um gravador de objetos XAML processa um uso de extensão de marcação e chama ProvideValue, o contexto de ter sido um uso de extensão de marcação persiste no fluxo de nós XAML, mas não na estrutura de objetos. No grafo de objeto, somente o valor é preservado. Se você tiver cenários de design ou outros motivos para persistir o uso da extensão de marcação original na saída serializada, deverá projetar sua própria infraestrutura para rastrear os usos da extensão de marcação do fluxo de nós XAML do caminho de carga. Você pode implementar um comportamento para recriar os elementos do fluxo de nós no caminho de carga e reproduzi-los para gravadores XAML para serialização no caminho de salvamento, substituindo o valor na posição apropriada do fluxo de nós.
Extensões de marcação no fluxo de nós XAML
Se você estiver trabalhando com um fluxo de nó XAML durante o processo de carregamento, uma extensão de marcação aparece no fluxo do nó como um objeto.
Se o uso da extensão de marcação empregar argumentos posicionais, ele será representado como um objeto inicial com um valor de início. Como uma representação aproximada de texto, o fluxo de nós é semelhante ao seguinte:
StartObject
(XamlType é o tipo de definição da extensão de marcação, não seu tipo de retorno)
StartMember
(nome do XamlMember é _InitializationText
)
Value
(o valor é os argumentos posicionais como uma cadeia de caracteres, incluindo os delimitadores intervenidores)
EndMember
EndObject
Um uso de extensão de marcação com argumentos nomeados é representado como um objeto que possui membros com os nomes relevantes, cada um definido com strings de texto.
Na verdade, invocar a ProvideValue
implementação de uma extensão de marcação requer o contexto do esquema XAML, pois isso requer mapeamento de tipo e criação de uma instância de tipo que dá suporte à extensão de marcação. Essa é uma das razões pelas quais as extensões de marcação XAML são preservadas dessa forma nos fluxos de nós padrão dos Serviços XAML do .NET – o componente leitor de um caminho de carga geralmente não dispõe do contexto de esquema XAML necessário.
Se você estiver trabalhando com um fluxo de nó XAML na trajetória de salvamento, geralmente não há nada presente em uma representação gráfica de objetos que possa informar que o objeto a ser serializado foi originalmente fornecido por um uso de uma extensão de marcação e um resultado ProvideValue
. Cenários que precisam persistir os usos de extensão de marcação para o arredondamento e, ao mesmo tempo, capturar outras alterações no grafo de objeto devem criar suas próprias técnicas para preservar o conhecimento de um uso de extensão de marcação da entrada XAML original. Por exemplo, para restaurar os usos de extensão de marcação, talvez seja necessário trabalhar com o fluxo de nós no caminho de salvamento para restaurar os usos de extensão de marcação ou executar algum tipo de mesclagem entre o XAML original e o XAML processado em ciclo. Algumas estruturas de implementação de XAML, como o WPF, usam tipos intermediários (expressões) para ajudar a representar casos em que os usos de extensão de marcação forneceram os valores.
Consulte também
.NET Desktop feedback