XAML condicional
A XAML condicional fornece uma forma de usar o método ApiInformation.IsApiContractPresent na marcação XAML. Com isso, você pode definir propriedades e instanciar objetos na marcação com base na presença de uma API sem a necessidade de usar code-behind. Analisa seletivamente elementos ou atributos para determinar se eles estarão disponíveis no momento da execução. Instruções condicionais são avaliadas no momento da execução, e os elementos qualificados com uma marca XAML condicional são analisados se forem avaliados como true; caso contrário, são ignorados.
A XAML condicional estará disponível a partir da Atualização para Criadores (versão 1703, compilação 15063). Para usar a XAML condicional, a Versão Mínima do seu projeto do Visual Studio deve ser definida como compilação 15063 (Atualização para Criadores) ou posterior, e a Versão de Destino deve ser definida como uma versão mais recente que a Mínima. Confira Aplicativos adaptáveis de versão para obter informações sobre como configurar seu projeto do Visual Studio.
Observação
Para criar um aplicativo adaptável de versão, uma Versão Mínima inferior à compilação 15063, você deve usar o código adaptável de versão, não a XAML.
Para obter informações de apoio importantes sobre ApiInformation e contratos de API, confira Aplicativos adaptáveis de versão.
Namespaces condicionais
Para usar um método condicional em XAML, primeiro é preciso declarar um Namespace XAML condicional na parte superior da sua página. Veja um exemplo de pseudocódigo de um namespace condicional:
xmlns:myNamespace="schema?conditionalMethod(parameter)"
Um namespace condicional pode ser dividido em duas partes pelo delimitador "?".
- O conteúdo que precede o delimitador indica o namespace ou o esquema que contém a API sendo referenciada.
- O conteúdo após o delimitador "?" representa o método condicional que determina se o namespace condicional avalia como true ou false.
Na maioria dos casos, o esquema será o namespace XAML padrão:
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
A XAML condicional é compatível com os seguintes métodos condicionais:
Método | Inverse |
---|---|
IsApiContractPresent(ContractName, VersionNumber) | IsApiContractNotPresent(ContractName, VersionNumber) |
IsTypePresent(ControlType) | IsTypeNotPresent(ControlType) |
IsPropertyPresent(ControlType, PropertyName) | IsPropertyNotPresent(ControlType, PropertyName) |
Vamos discutir esses métodos em outras seções deste artigo.
Observação
Recomendamos o uso de IsApiContractPresent e IsApiContractNotPresent. Outras condicionais não são compatíveis com a experiência de design do Visual Studio.
Criar um namespace e definir uma propriedade
Neste exemplo, será exibido "Olá, XAML Condicional", como o conteúdo de um bloco de texto se o aplicativo for executado no Fall Creators Update ou versões posteriores, e padrão para nenhum conteúdo se estiver em uma versão anterior.
Primeiro, defina um namespace personalizado com o prefixo 'contract5Present' e use o namespace XAML padrão (https://schemas.microsoft.com/winfx/2006/xaml/presentation
) como o esquema contendo a propriedade TextBlock.Text. Para torná-lo um namespace condicional, adicione o delimitador "?" após o esquema.
Depois, defina uma condicional que retorne true nos dispositivos que estão executando o Fall Creators Update ou posterior. Use o IsApiContractPresent do método ApiInformation para verificar a 5ª versão do UniversalApiContract. A versão 5 do UniversalApiContract foi lançada com o Fall Creators Update (SDK 16299).
xmlns:contract5Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,5)"
Após a definição do namespace, você coloca o prefixo do namespace na propriedade Text do seu TextBox para qualificá-lo como uma propriedade que deve ser definida de forma condicional no momento da execução.
<TextBlock contract5Present:Text="Hello, Conditional XAML"/>
Veja a XAML completa.
<Page
x:Class="ConditionalTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:contract5Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,5)">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<TextBlock contract5Present:Text="Hello, Conditional XAML"/>
</Grid>
</Page>
Ao executar esse exemplo no Fall Creators Update, o texto “Olá, XAML Condicional” é exibido; ao executá-lo na Atualização para Criadores, nenhum texto é exibido.
A XAML condicional permite realizar as verificações de API que, em vez disso, você pode fazer no código da marcação. Aqui está o código equivalente para essa verificação.
if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 5))
{
textBlock.Text = "Hello, Conditional XAML";
}
Observe que, embora o método IsApiContractPresent use uma cadeia de caracteres para o parâmetro contractName, você não o coloca entre aspas (" ") na declaração de namespace de XAML.
Usar as condições if/else
No exemplo anterior, a propriedade Text é definida apenas quando o aplicativo é executado no Fall Creators Update. Mas e se você quiser mostrar um texto diferente quando ele é executado na Atualização para Criadores? Você poderia tentar definir a propriedade Text sem um qualificador condicional, como este.
<!-- DO NOT USE -->
<TextBlock Text="Hello, World" contract5Present:Text="Hello, Conditional XAML"/>
Ela funcionará quando for executada na Atualização para Criadores, mas, quando for executada no Fall Creators Update, ocorrerá um erro informando que a propriedade Text foi definida mais de uma vez.
Para definir um texto diferente quando o aplicativo é executado em versões diferentes do Windows 10, outra condição é necessária. Uma XAML condicional fornece o inverso de cada método ApiInformation compatível para permitir que você crie cenários condicionais if/else como este.
O método IsApiContractPresent retorna true se o dispositivo atual contiver o contrato especificado e o número de versão. Por exemplo, suponha que seu aplicativo está sendo executado na Atualização para Criadores, que tem a 4ª versão do contrato de API universal.
Várias chamadas para IsApiContractPresent apresentariam estes resultados:
- IsApiContractPresent(Windows.Foundation.UniversalApiContract, 5) = false
- IsApiContractPresent(Windows.Foundation.UniversalApiContract, 4) = true
- IsApiContractPresent(Windows.Foundation.UniversalApiContract, 3) = true
- IsApiContractPresent(Windows.Foundation.UniversalApiContract, 2) = true
- IsApiContractPresent(Windows.Foundation.UniversalApiContract, 1) = true.
IsApiContractNotPresent retorna o inverso de IsApiContractPresent. Várias chamadas para IsApiContractPresent apresentariam estes resultados:
- IsApiContractNotPresent(Windows.Foundation.UniversalApiContract, 5) = true
- IsApiContractNotPresent(Windows.Foundation.UniversalApiContract, 4) = false
- IsApiContractNotPresent(Windows.Foundation.UniversalApiContract, 3) = false
- IsApiContractNotPresent(Windows.Foundation.UniversalApiContract, 2) = false
- IsApiContractNotPresent(Windows.Foundation.UniversalApiContract, 1) = false
Para usar a condição inversa, crie um segundo namespace de XAML condicional que usa o condicional IsApiContractNotPresent. Neste exemplo, temos o prefixo "contract5NotPresent".
xmlns:contract5NotPresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractNotPresent(Windows.Foundation.UniversalApiContract,5)"
xmlns:contract5Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,5)"
Com os namespaces definidos, você pode definir a propriedade Text duas vezes, contanto que sejam prefixados com qualificadores que garantam que apenas uma configuração de propriedade seja usada no momento da execução, como a seguir:
<TextBlock contract5NotPresent:Text="Hello, World"
contract5Present:Text="Hello, Fall Creators Update"/>
Veja outro exemplo que define o plano de fundo de um botão. O recurso Material acrílico estará disponível a partir do Fall Creators Update. Assim, você usará o acrílico para o plano de fundo quando o aplicativo for executado no Fall Creators Update. Não estará disponível em versões anteriores. Por isso, nesses casos, você define o plano de fundo como vermelho.
<Button Content="Button"
contract5NotPresent:Background="Red"
contract5Present:Background="{ThemeResource SystemControlAcrylicElementBrush}"/>
Criar controles e propriedades de associação
Até o momento, você já viu como definir as propriedades usando a XAML condicional, mas também é possível instanciar controles de forma condicional com base no contrato de API disponível no momento da execução.
Neste exemplo, um ColorPicker é instanciado quando o aplicativo é executado no Fall Creators Update em que o controle está disponível. O ColorPicker não estará disponível antes do Fall Creators Update. Portanto, quando o aplicativo é executado em versões anteriores, use um ComboBox para fornecer opções de cor simplificadas para o usuário.
<contract5Present:ColorPicker x:Name="colorPicker"
Grid.Column="1"
VerticalAlignment="Center"/>
<contract5NotPresent:ComboBox x:Name="colorComboBox"
PlaceholderText="Pick a color"
Grid.Column="1"
VerticalAlignment="Center">
É possível usar qualificadores condicionais com formas diferentes de Sintaxe da propriedade XAML. Neste exemplo, a propriedade Fill do retângulo é definida usando a sintaxe de elemento de propriedade para o Fall Creators Update e uma sintaxe de atributo para versões anteriores.
<Rectangle x:Name="colorRectangle" Width="200" Height="200"
contract5NotPresent:Fill="{x:Bind ((SolidColorBrush)((FrameworkElement)colorComboBox.SelectedItem).Tag), Mode=OneWay}">
<contract5Present:Rectangle.Fill>
<SolidColorBrush contract5Present:Color="{x:Bind colorPicker.Color, Mode=OneWay}"/>
</contract5Present:Rectangle.Fill>
</Rectangle>
Ao associar uma propriedade com outra que depende de um namespace condicional, é preciso usar a mesma condição em ambas as propriedades. Neste exemplo, colorPicker.Color
depende do namespace condicional "contract5Present". Por isso, também é preciso colocar o prefixo "contract5Present" na propriedade SolidColorBrush.Color. (Ou é possível colocar o prefixo "contract5Present" na propriedade SolidColorBrush em vez da propriedade Color.) Caso contrário, você obterá um erro de tempo de compilação.
<SolidColorBrush contract5Present:Color="{x:Bind colorPicker.Color, Mode=OneWay}"/>
Esta é a XAML completa que demonstra esses cenários. Este exemplo contém um retângulo e uma interface de usuário que permite definir a cor do retângulo.
Quando o aplicativo é executado no Fall Creators Update, use ColorPicker para que o usuário possa definir a cor. O ColorPicker não estará disponível antes do Fall Creators Update. Portanto, quando o aplicativo é executado em versões anteriores, use uma caixa de combinação para fornecer opções de cor simplificadas para o usuário.
<Page
x:Class="ConditionalTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:contract5Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,5)"
xmlns:contract5NotPresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractNotPresent(Windows.Foundation.UniversalApiContract,5)">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Rectangle x:Name="colorRectangle" Width="200" Height="200"
contract5NotPresent:Fill="{x:Bind ((SolidColorBrush)((FrameworkElement)colorComboBox.SelectedItem).Tag), Mode=OneWay}">
<contract5Present:Rectangle.Fill>
<SolidColorBrush contract5Present:Color="{x:Bind colorPicker.Color, Mode=OneWay}"/>
</contract5Present:Rectangle.Fill>
</Rectangle>
<contract5Present:ColorPicker x:Name="colorPicker"
Grid.Column="1"
VerticalAlignment="Center"/>
<contract5NotPresent:ComboBox x:Name="colorComboBox"
PlaceholderText="Pick a color"
Grid.Column="1"
VerticalAlignment="Center">
<ComboBoxItem>Red
<ComboBoxItem.Tag>
<SolidColorBrush Color="Red"/>
</ComboBoxItem.Tag>
</ComboBoxItem>
<ComboBoxItem>Blue
<ComboBoxItem.Tag>
<SolidColorBrush Color="Blue"/>
</ComboBoxItem.Tag>
</ComboBoxItem>
<ComboBoxItem>Green
<ComboBoxItem.Tag>
<SolidColorBrush Color="Green"/>
</ComboBoxItem.Tag>
</ComboBoxItem>
</contract5NotPresent:ComboBox>
</Grid>
</Page>