XAML Bersyarat

XAML Bersyarat menyediakan cara untuk menggunakan metode ApiInformation.IsApiContractPresent langsung dalam markup XAML. Anda dapat mengatur properti berdasarkan keberadaan kontrak API tingkat OS tanpa menulis kode di belakang. Pernyataan bersyarat dievaluasi saat runtime — elemen yang memenuhi kondisi tag XAML bersyarat diurai jika hasil evaluasinya adalah true dan diabaikan jika tidak.

Mulai dari SDK Aplikasi Windows 2.0, Anda juga dapat menentukan kondisi Anda sendiri dengan menerapkan antarmuka IXamlCondition. Kondisi kustom memungkinkan Anda menyertakan atau mengecualikan markup berdasarkan status khusus aplikasi, seperti bendera fitur atau pengaturan konfigurasi. Untuk informasi selengkapnya, lihat Membuat kondisi kustom.

XAML bersyarat memerlukan Windows 10 versi 1809 (build 17763) atau yang lebih baru, yang merupakan versi OS minimum untuk aplikasi SDK Aplikasi Windows.

Prasyarat

Important

Metode kondisional bawaan menggunakan metode ApiInformation, yang memeriksa apakah kontrak dan jenis API Windows Runtime (Windows.*) tersedia dan disediakan oleh OS. Pemeriksaan ini tidak berlaku untuk kontrol WinUI 3 (Microsoft.UI.Xaml.*), karena WinUI 3 disertakan bersama aplikasi Anda melalui SDK Aplikasi Windows, bukan bersama OS — setiap kontrol WinUI 3 yang menjadi target build aplikasi Anda selalu tersedia saat runtime, apa pun build Windows 10/11 yang dijalankan perangkat tersebut. #if direktif prapemroses juga tidak membantu di sini: direktif ini dievaluasi saat kompilasi berdasarkan kerangka kerja target, bukan saat runtime berdasarkan sistem operasi atau versi SDK Aplikasi Windows yang benar-benar terinstal. Untuk membatasi ketersediaan fitur berdasarkan versi SDK Aplikasi Windows yang digunakan aplikasi Anda, periksa versi SDK saat proses build atau bungkus pemanggilan API dengan try/catch. Lihat Kode adaptif versi untuk detailnya.

Untuk informasi latar belakang tentang ApiInformation dan kontrak API, lihat Aplikasi yang adaptif terhadap versi.

Namespace bersyarat

Untuk menggunakan metode bersyarah di XAML, deklarasikan namespace XAML bersyarkat di bagian atas halaman Anda:

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

Isi sebelum pembatas ? adalah namespace atau skema. Konten setelah ? adalah metode kondisional yang menentukan apakah namespace mengevaluasi ke true atau false.

Dalam kebanyakan kasus, skema adalah namespace XAML default:

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

XAML bersyarat mendukung metode kondisional berikut:

Metode Terbalik
IsApiContractPresent(ContractName, VersionNumber) IsApiContractNotPresent(ContractName, VersionNumber)
IsTypePresent(ControlType) IsTypeNotPresent(ControlType)
IsPropertyPresent(ControlType, PropertyName) IsPropertyNotPresent(ControlType, PropertyName)

Anda juga dapat menggunakan kondisi yang Anda tentukan di aplikasi Anda. Untuk informasi selengkapnya, lihat Membuat kondisi kustom.

Note

Gunakan IsApiContractPresent dan IsApiContractNotPresent untuk pengalaman waktu desain terbaik. Kondisi lainnya tidak sepenuhnya didukung dalam pengalaman desain Visual Studio.

Atur properti secara bersyarat

Contoh ini menampilkan teks dalam TextBlock hanya ketika aplikasi berjalan di Windows 10 versi 1903 (Pembaruan Mei 2019, build 18362) atau yang lebih baru — pemeriksaan kontrak ini bermakna karena versi tersebut lebih baru daripada baseline 1809 SDK Aplikasi Windows.

Pertama, tentukan namespace bersyarah:

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

Kemudian beri awalan pada properti dengan namespace kondisional:

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

Berikut adalah markup lengkapnya:

<Page
    x:Class="ConditionalTest.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:contract8Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,8)">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <TextBlock contract8Present:Text="Hello, Conditional XAML"/>
    </Grid>
</Page>

Kode cek masuk yang setara di belakang:

TextBlock textBlock = new TextBlock();

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

Note

Meskipun IsApiContractPresent mengambil string untuk parameter nama kontrak, Anda tidak memasukkannya dalam tanda kutip dalam deklarasi namespace XAML.

Karena versi minimum OS yang didukung oleh SDK Aplikasi Windows adalah 1809 (UniversalApiContract versi 7), memeriksa versi kontrak API pada atau di bawah 7 di aplikasi SDK Aplikasi Windows selalu menghasilkan true dan tidak memberikan informasi yang berguna. Hanya periksa versi kontrak yang lebih tinggi dari 7.

Gunakan kondisi if/else

Untuk mengatur nilai yang berbeda tergantung pada kontrak API, tentukan namespace kondisional positif dan negatif:

xmlns:contract8NotPresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractNotPresent(Windows.Foundation.UniversalApiContract,8)"
xmlns:contract8Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,8)"

Kemudian atur properti tersebut dua kali, masing-masing dengan prefiks kondisional yang berbeda. Hanya satu yang diterapkan saat dijalankan:

<TextBlock contract8NotPresent:Text="Hello, World"
           contract8Present:Text="Hello, May 2019 Update or later"/>

Buat instance kontrol berdasarkan kondisi

Note

Membuat instans elemen secara kondisional berdasarkan kontrak OS API — dibandingkan dengan pengaturan properti secara kondisional — adalah pola khusus UWP. Ini tidak berlaku untuk kontrol WinUI 3.

Di UWP, pola ini memungkinkan Anda kembali ke kontrol yang lebih Windows.UI.Xaml.Controls lama ketika yang lebih baru tidak tersedia di OS. Dalam aplikasi SDK Aplikasi Windows, kontrol WinUI 3 (Microsoft.UI.Xaml.Controls.*) disertakan bersama aplikasi Anda melalui SDK Aplikasi Windows, bukan bersama OS. Setiap kontrol yang menjadi dasar pembuatan aplikasi Anda — termasuk ColorPicker — dijamin tersedia pada saat runtime, jadi Anda tidak perlu memeriksa versi OS sebelum membuat instansnya.

Jika Anda perlu membatasi penggunaan kontrol atau API WinUI 3 berdasarkan versi SDK Aplikasi Windows yang ditargetkan aplikasi Anda, lakukan pemeriksaan tersebut saat build (dengan menargetkan versi paket minimum SDK Aplikasi Windows) atau bungkus pemanggilan runtime dalam try/catch — bukan dengan XAML bersyarat.

Untuk menyertakan atau mengecualikan elemen berdasarkan logika yang ditentukan aplikasi Anda, seperti bendera fitur, gunakan kondisi kustom.

Buat kondisi kustom

Mulai dari SDK Aplikasi Windows 2.0, Anda dapat menentukan kondisi Anda sendiri dan menggunakannya dengan sintaks namespace bersyarat. Kondisi kustom memungkinkan Anda menyertakan atau mengecualikan markup berdasarkan status khusus aplikasi, seperti bendera fitur, pengaturan konfigurasi, atau kemampuan perangkat. Seperti metode kondisional bawaan, kondisi kustom dievaluasi ketika XAML diurai saat runtime.

Ikon Galeri WinUI 3 Aplikasi Galeri WinUI 3 mencakup contoh interaktif kontrol dan fitur WinUI. Dapatkan aplikasi dari Microsoft Store atau telusuri kode sumber pada GitHub.

Note

IXamlConditionmenggantikan IXamlPredicate antarmuka dari rilis eksperimental SDK Aplikasi Windows 2.0.

Buat kondisi

Untuk membuat kondisi, tentukan kelas yang berasal dari DependencyObject dan mengimplementasikan IXamlCondition. Pengurai XAML memanggil metode Evaluate dan meneruskan teks di antara tanda kurung pada deklarasi namespace bersyarat sebagai parameter argument. Kembalikan true untuk menyertakan markup yang memenuhi syarat, atau false untuk mengabaikannya.

Contoh ini, dari sampel Galeri WinUI 3, mengevaluasi bendera fitur yang disimpan aplikasi dalam kamus:

using System.Collections.Generic;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Markup;

namespace MyApp;

public sealed partial class FeatureFlagCondition : DependencyObject, IXamlCondition
{
    public static IDictionary<string, bool> FeatureFlags { get; } = new Dictionary<string, bool>
    {
        ["NewExperience"] = true,
        ["LegacyMode"] = false,
    };

    // The XAML parser calls Evaluate with the text between the parentheses
    // in the conditional namespace declaration, for example "NewExperience".
    public bool Evaluate(string argument)
    {
        return FeatureFlags.TryGetValue(argument, out bool enabled) && enabled;
    }
}

Mendeklarasikan namespace bersyarat untuk kondisi tersebut

Pertama, petakan namespace yang berisi kelas kondisi Anda dengan menggunakan deklarasi using:. Kemudian, setelah pemisah ? namespace kondisional, referensikan kelas melalui awalan tersebut dan teruskan argumen dalam tanda kurung:

xmlns:cond="using:MyApp"
xmlns:newExp="http://schemas.microsoft.com/winfx/2006/xaml/presentation?cond:FeatureFlagCondition(NewExperience)"
xmlns:legacy="http://schemas.microsoft.com/winfx/2006/xaml/presentation?cond:FeatureFlagCondition(LegacyMode)"

Dalam contoh ini, pengurai memanggil Evaluate("NewExperience") untuk markup yang menggunakan awalan newExp, dan Evaluate("LegacyMode") untuk markup yang menggunakan awalan legacy.

Gunakan kondisi pada elemen, atribut, dan setter

Gunakan awalan kondisional dengan cara yang sama seperti Anda menggunakan namespace kondisional bawaan. Contoh-contoh ini didasarkan pada sampel Galeri WinUI 3.

Untuk menyertakan elemen hanya ketika kondisi adalah true, tambahkan prefiks pada elemen:

<StackPanel Spacing="8">
    <!-- Included only when FeatureFlagCondition.Evaluate("NewExperience") returns true. -->
    <newExp:InfoBar Title="New experience" IsOpen="True" Severity="Success"
                    Message="This InfoBar is included because the NewExperience flag is true." />

    <!-- Included only when FeatureFlagCondition.Evaluate("LegacyMode") returns true. -->
    <legacy:InfoBar Title="Legacy mode" IsOpen="True" Severity="Warning"
                    Message="This InfoBar is included because the LegacyMode flag is true." />
</StackPanel>

Untuk mengatur properti hanya ketika kondisi adalah true, awali atribut:

<!-- Make sure that no more than one of these conditions is true at runtime. -->
<Button newExp:Content="Open the new editor"
        legacy:Content="Open the classic editor" />

Untuk menerapkan setter gaya hanya saat kondisi adalah true, awali Setter elemen:

<Page.Resources>
    <Style x:Key="ConditionalHeadingStyle" TargetType="TextBlock">
        <newExp:Setter Property="FontWeight" Value="SemiBold" />
        <newExp:Setter Property="FontSize" Value="28" />
        <legacy:Setter Property="FontWeight" Value="Normal" />
        <legacy:Setter Property="FontSize" Value="18" />
    </Style>
</Page.Resources>

Atur status sebelum XAML diurai

Pengurai menyimpan hasil Evaluate untuk setiap kombinasi kondisi dan argumen untuk masa pakai proses. Jika Anda mengubah status yang dibaca oleh kondisi setelah hasilnya di-cache, markup yang sudah diurai tidak berubah, dan markup yang diurai nanti masih menggunakan hasil yang di-cache. Untuk menggunakan nilai lain, mulai ulang aplikasi.

Atur status yang dibaca kondisi Anda sebelum pengurai mengevaluasinya, misalnya di startup aplikasi atau sebelum Anda memanggil InitializeComponent di konstruktor halaman:

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        // Set the flags before InitializeComponent so that the XAML parser
        // uses these values when it evaluates the conditions.
        FeatureFlagCondition.FeatureFlags["NewExperience"] = true;
        FeatureFlagCondition.FeatureFlags["LegacyMode"] = false;

        this.InitializeComponent();
    }
}

Limitations

  • Dua elemen tidak dapat memiliki x:Name yang sama, bahkan jika hanya satu dari elemen tersebut yang disertakan saat runtime.
  • Jika Anda menerapkan lebih dari satu kondisi ke atribut yang sama, pastikan hanya salah satu dari kondisi tersebut yang bernilai true saat runtime. Jika lebih dari satu ekspresi dievaluasi menjadi true, pengurai melempar pengecualian.
  • Karena kondisi dievaluasi saat runtime, pengkompilasi XAML tidak dapat memeriksanya untuk konsistensi logis. Uji setiap kombinasi nilai kondisi yang didukung aplikasi Anda.
  • Kondisi kustom tidak berfungsi dengan item dari x: namespace layanan (http://schemas.microsoft.com/winfx/2006/xaml), seperti x:Uid dan x:Key.