XAML condizionale

XAML condizionale consente di usare il metodo ApiInformation.IsApiContractPresent nel markup XAML. Puoi così impostare le proprietà e creare istanze di oggetti nel markup in base alla presenza di un'API senza dover usare code-behind. Analizza selettivamente gli elementi o gli attributi per determinare se saranno disponibili in fase di esecuzione. Le istruzioni condizionali vengono valutate in fase di esecuzione e gli elementi qualificati con un tag XAML condizionale vengono analizzati se restituiscono true. In caso contrario, vengono ignorati.

XAML condizionale è disponibile a partire da Creators Update (versione 1703, build 15063). Per usare XAML condizionale, devi impostare la versione minima del progetto di Visual Studio sulla build 15063 (Creators Update) o versioni successive e la versione di destinazione su una versione successiva a quella minima. Per altre informazioni sulla configurazione del progetto di Visual Studio, vedi App adattive per la versione.

Nota

Per creare un'app adattiva per la versione con una versione minima precedente alla build 15063, devi usare il codice adattivo per la versione, non XAML.

Per informazioni generali importanti su ApiInformation e sui contratti API, vedi App adattive per la versione.

Spazi dei nomi condizionali

Per usare un metodo condizionale in XAML, devi prima dichiarare uno spazio dei nomi XAML condizionale nella parte superiore della pagina. Ecco un esempio di pseudocodice di uno spazio dei nomi condizionale:

xmlns:myNamespace="schema?conditionalMethod(parameter)"

Uno spazio dei nomi condizionale può essere suddiviso in due parti separate dal delimitatore "?".

  • Il contenuto che precede il delimitatore indica lo spazio dei nomi o lo schema contenente l'API a cui si fa riferimento.
  • Il contenuto dopo il delimitatore "?" rappresenta il metodo condizionale che determina se lo spazio dei nomi condizionale restituisce true o false.

Nella maggior parte dei casi, lo schema sarà lo spazio dei nomi XAML predefinito:

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

XAML condizionale supporta i metodi condizionali seguenti:

Metodo Metodo inverso
IsApiContractPresent(ContractName, VersionNumber) IsApiContractNotPresent(ContractName, VersionNumber)
IsTypePresent(ControlType) IsTypeNotPresent(ControlType)
IsPropertyPresent(ControlType, PropertyName) IsPropertyNotPresent(ControlType, PropertyName)

Parleremo di questi metodi in maggior dettaglio nelle sezioni successive di questo articolo.

Nota

Ti consigliamo di usare IsApiContractPresent e IsApiContractNotPresent. Le altre istruzioni condizionali non sono completamente supportate nell'esperienza di progettazione di Visual Studio.

Creare uno spazio dei nomi e impostare una proprietà

In questo esempio, visualizzi "Hello, Conditional XAML" come contenuto di un blocco di testo se l'app viene eseguita in Fall Creators Update o versioni successive, mentre non visualizzi alcun contenuto se viene eseguita in una versione precedente.

Definisci innanzitutto uno spazio dei nomi personalizzato con il prefisso "contract5Present" e usa lo spazio dei nomi XAML predefinito (https://schemas.microsoft.com/winfx/2006/xaml/presentation) come schema contenente la proprietà TextBlock.Text. Per trasformare tale spazio dei nomi in uno spazio dei nomi condizionale, aggiungi il delimitatore "?" dopo lo schema.

Definisci quindi un'istruzione condizionale che restituisca true nei dispositivi in cui è in esecuzione Fall Creators Update o versioni successive. Puoi verificare la presenza della versione 5 di UniversalApiContract usando il metodo ApiInformation IsApiContractPresent. La versione 5 di UniversalApiContract è stata rilasciata con Fall Creators Update (SDK 16299).

xmlns:contract5Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,5)"

Dopo aver definito lo spazio dei nomi, anteponi il prefisso dello spazio dei nomi alla proprietà Text del controllo TextBox, per qualificarla come proprietà che deve essere impostata in modo condizionale in fase di esecuzione.

<TextBlock contract5Present:Text="Hello, Conditional XAML"/>

Ecco il codice XAML completo.

<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>

Quando esegui questo esempio in Fall Creators Update, viene visualizzato il testo "Hello, Conditional XAML", mentre non viene visualizzato alcun testo quando esegui l'esempio in Creators Update.

XAML condizionale consente di effettuare i controlli delle API che puoi invece eseguire nel codice del markup. Ecco il codice equivalente per questo controllo.

if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 5))
{
    textBlock.Text = "Hello, Conditional XAML";
}

Tieni presente che anche se il metodo IsApiContractPresent accetta una stringa per il parametro contractName, non devi inserirla tra virgolette (" ") nella dichiarazione dello spazio dei nomi XAML.

Usare le condizioni if/else

Nell'esempio precedente, la proprietà Text è impostata solo quando l'app viene eseguita in Fall Creators Update. Ma cosa succede se vuoi visualizzare un testo diverso quando viene eseguita in Creators Update? Potresti provare a impostare la proprietà Text senza un qualificatore condizionale, in questo modo.

<!-- DO NOT USE -->
<TextBlock Text="Hello, World" contract5Present:Text="Hello, Conditional XAML"/>

Tale metodo funziona quando viene eseguita in Creators Update, ma quando viene eseguita in Fall Creators Update riceverai un errore che indica che la proprietà Text è impostata più volte.

Per impostare un testo diverso quando l'app è in esecuzione in versioni diverse da Windows 10, devi disporre di un'altra condizione. XAML condizionale fornisce un metodo inverso di ogni metodo ApiInformation supportato per consentirti di creare scenari condizionali if/else simili al seguente.

Il metodo IsApiContractPresent restituisce true se il dispositivo corrente contiene il numero di contratto e versione specificati. Supponi, ad esempio, che l'app sia in esecuzione in Creators Update con la versione 4 del contratto API universale.

Varie chiamate a IsApiContractPresent avranno i risultati seguenti:

  • 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 restituisce il risultato inverso rispetto a IsApiContractPresent. Le chiamate a IsApiContractNotPresent avranno i risultati seguenti:

  • 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

Per usare la condizione inversa, crea un secondo spazio dei nomi XAML condizionale che usi l'istruzione condizionale IsApiContractNotPresent. In questo caso, il prefisso è "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)"

Con entrambi gli spazi dei nomi definiti, puoi impostare la proprietà Text due volte, purché inserisci come prefisso i qualificatori che garantiscono che in fase di esecuzione venga usata solo l'impostazione di una proprietà, in questo modo:

<TextBlock contract5NotPresent:Text="Hello, World"
           contract5Present:Text="Hello, Fall Creators Update"/>

Ecco un altro esempio che imposta lo sfondo di un pulsante. Poiché la funzionalità Materiale acrilico è disponibile a partire da Fall Creators Update, userai l'acrilico per lo sfondo quando l'app viene eseguita in questa versione. Tale funzionalità non è disponibile nelle versioni precedenti. In questi casi, imposta quindi lo sfondo su rosso.

<Button Content="Button"
        contract5NotPresent:Background="Red"
        contract5Present:Background="{ThemeResource SystemControlAcrylicElementBrush}"/>

Creare controlli e associare proprietà

Finora abbiamo visto come impostare le proprietà con XAML condizionale, ma puoi anche creare istanze di controlli in modo condizionale in base al contratto API disponibile in fase di esecuzione.

In questo caso, viene creata un'istanza di ColorPicker quando l'app viene eseguita in Fall Creators Update, in cui è disponibile il controllo. ColorPicker non è disponibile nelle versioni precedenti a Fall Creators Update. Quando l'app viene eseguita in una di queste versioni, usa quindi un oggetto ComboBox per fornire all'utente scelte di colore semplificate.

<contract5Present:ColorPicker x:Name="colorPicker"
                              Grid.Column="1"
                              VerticalAlignment="Center"/>

<contract5NotPresent:ComboBox x:Name="colorComboBox"
                              PlaceholderText="Pick a color"
                              Grid.Column="1"
                              VerticalAlignment="Center">

Puoi usare i qualificatori condizionali con diversi tipi di sintassi delle proprietà XAML. In questo caso, la proprietà Fill del rettangolo viene impostata usando la sintassi degli elementi della proprietà per Fall Creators Update e la sintassi degli attributi per le versioni precedenti.

<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>

Quando associ una proprietà a un'altra proprietà che dipende da uno spazio dei nomi condizionale, devi usare la stessa condizione in entrambe le proprietà. In questo caso, colorPicker.Color dipende dallo spazio dei nomi condizionale "contract5Present", devi quindi inserire il prefisso "contract5Present" anche nella proprietà SolidColorBrush.Color. In alternativa, puoi inserire il prefisso "contract5Present" in SolidColorBrush anziché nella proprietà Color. In caso contrario, verrà generato un errore in fase di compilazione.

<SolidColorBrush contract5Present:Color="{x:Bind colorPicker.Color, Mode=OneWay}"/>

Ecco il codice XAML completo che illustra questi scenari. Questo esempio contiene un rettangolo e un'interfaccia utente in cui puoi impostare il colore del rettangolo.

Quando l'app viene eseguita in Fall Creators Update, usa un controllo ColorPicker per consentire all'utente di impostare il colore. ColorPicker non è disponibile prima di Fall Creators Update. Quando l'app viene eseguita nelle versioni precedenti, usa quindi una casella combinata per fornire all'utente scelte di colore semplificate.

<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>