Voorwaardelijke XAML

Voorwaardelijk XAML biedt een manier om de methode ApiInformation.IsApiContractPresent rechtstreeks in XAML-opmaak te gebruiken. U kunt eigenschappen instellen op basis van de aanwezigheid van een API-contract op besturingssysteemniveau zonder code achter te schrijven. Voorwaardelijke instructies worden tijdens de uitvoering geëvalueerd — elementen die van een voorwaardelijke XAML-tag zijn voorzien, worden geparseerd als deze wordt geëvalueerd als true en anders genegeerd.

Vanaf Windows App SDK 2.0 kunt u ook uw eigen voorwaarden definiëren door de IXamlCondition-interface te implementeren. Met aangepaste voorwaarden kunt u markup opnemen of uitsluiten op basis van app-specifieke status, zoals featureflags of configuratie-instellingen. Zie Aangepaste voorwaarden maken voor meer informatie.

Voor voorwaardelijke XAML is Windows 10 versie 1809 (build 17763) of hoger vereist. Dit is de minimale versie van het besturingssysteem voor Windows App SDK-apps.

Prerequisites

Important

De ingebouwde voorwaardelijke methoden gebruiken ApiInformation methoden, die controleren op de aanwezigheid van Windows Runtime (Windows.*) API-contracten en -typen die door het besturingssysteem worden geleverd. Deze controles zijn niet van toepassing op WinUI 3(Microsoft.UI.Xaml.*)-besturingselementen, omdat WinUI 3 wordt geleverd met uw app via het Windows App SDK in plaats van met het besturingssysteem. Elke WinUI 3-besturing waarop uw app is gebouwd, is altijd aanwezig tijdens runtime, ongeacht de Windows 10/11-build waarop het apparaat wordt uitgevoerd. #ifpreprocessorrichtlijnen helpen hier ook niet: ze worden geëvalueerd tijdens het compileren op basis van het doelframework, niet tijdens runtime op basis van het besturingssysteem of Windows App SDK versie die daadwerkelijk is geïnstalleerd. Als u een functie wilt gateen op de Windows App SDK versie waarop uw app wordt uitgevoerd, controleert u de SDK-versie tijdens de build of gebruikt u een try/catch rond de API-aanroep. Zie Adaptieve versiecode voor meer informatie.

Zie ApiInformation voor achtergrondinformatie over en API-contracten.

Voorwaardelijke naamruimten

Als u een voorwaardelijke methode in XAML wilt gebruiken, declareert u een voorwaardelijke XAML-naamruimte boven aan de pagina:

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

De inhoud vóór het ? scheidingsteken is de naamruimte of het schema. De inhoud na ? is de conditionele methode die bepaalt of de naamruimte resulteert in true of false.

In de meeste gevallen is het schema de standaard XAML-naamruimte:

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

Voorwaardelijke XAML ondersteunt deze voorwaardelijke methoden:

Method Invers
IsApiContractPresent(ContractName, VersionNumber) IsApiContractNotPresent(ContractName, VersionNumber)
IsTypePresent(ControlType) IsTypeNotPresent(ControlType)
IsPropertyPresent(ControlType, PropertyName) IsPropertyNotPresent(ControlType, PropertyName)

U kunt ook een voorwaarde gebruiken die u in uw app definieert. Zie Aangepaste voorwaarden maken voor meer informatie.

Note

Gebruik IsApiContractPresent en IsApiContractNotPresent voor de beste ontwerptijdervaring. Andere voorwaarden worden niet volledig ondersteund in de ontwerpervaring van Visual Studio.

Een eigenschap voorwaardelijk instellen

In dit voorbeeld wordt tekst in een TextBlock alleen weergegeven wanneer de app wordt uitgevoerd op Windows 10 versie 1903 (update van mei 2019, build 18362) of nieuwer — een contractcontrole die zinvol is omdat deze nieuwer is dan de 1809-ondergrens van de Windows App SDK.

Definieer eerst een voorwaardelijke naamruimte:

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

Voeg vervolgens de eigenschap toe aan de voorwaardelijke naamruimte:

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

Dit is de volledige markering:

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

De equivalente incheckcode achter:

TextBlock textBlock = new TextBlock();

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

Note

IsApiContractPresent Hoewel u een tekenreeks gebruikt voor de parameter contractnaam, plaatst u deze niet tussen aanhalingstekens in de XAML-naamruimtedeclaratie.

Omdat de minimaal ondersteunde OS-versie van de Windows App SDK 1809 (UniversalApiContract versie 7) is, komt een controle op een contractversie van 7 of lager in een Windows App SDK-app altijd uit op true en levert die geen nuttige informatie op. Controleer alleen op contractversies die hoger zijn dan 7.

If/else-voorwaarden gebruiken

Als u verschillende waarden wilt instellen, afhankelijk van het API-contract, definieert u zowel de positieve als negatieve voorwaardelijke naamruimten:

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

Stel vervolgens de eigenschap twee keer in, elk met een ander voorwaardelijk voorvoegsel. Er wordt slechts één toegepast tijdens runtime:

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

Besturingselementen voorwaardelijk instantiëren

Note

Het voorwaardelijk instantiëren van een element op basis van een OS API-contract , in tegenstelling tot het voorwaardelijk instellen van een eigenschap , is een UWP-specifiek patroon. Dit is niet van toepassing op WinUI 3-besturingselementen.

In UWP kon u met dit patroon terugvallen op een ouder Windows.UI.Xaml.Controls-besturingselement wanneer een nieuwer besturingselement niet beschikbaar was in het besturingssysteem. In een Windows App SDK-app worden WinUI 3-besturingselementen (Microsoft.UI.Xaml.Controls.*) samen met uw app meegeleverd via de Windows App SDK, niet via het besturingssysteem. Elk besturingselement waarvoor uw app is gebouwd — inclusief ColorPicker — is gegarandeerd aanwezig tijdens uitvoering, dus u hoeft de versie van het besturingssysteem niet te controleren voordat u het instantieert.

Als u een WinUI 3-besturingselement of API moet afschermen op basis van de versie van de Windows App SDK waarop uw app is gericht, voer die controle dan uit tijdens het bouwen (door een minimale pakketversie van de Windows App SDK als doel te nemen) of verpak de runtime-aanroep in een try/catch — niet met conditionele XAML.

Als u elementen wilt opnemen of uitsluiten op basis van logica die uw app definieert, zoals een functievlag, gebruikt u een aangepaste voorwaarde.

Aangepaste condities maken

Vanaf Windows App SDK 2.0 kunt u uw eigen voorwaarden definiëren en gebruiken met de syntaxis van de voorwaardelijke naamruimte. Met een aangepaste voorwaarde kunt u markup opnemen of uitsluiten op basis van app-specifieke status, zoals featureflags, configuratie-instellingen of apparaatmogelijkheden. Net als bij de ingebouwde voorwaardelijke methoden worden aangepaste voorwaarden geëvalueerd wanneer de XAML tijdens runtime wordt geparseerd.

Pictogram WinUI 3-galerie De WinUI 3 Gallery-app bevat interactieve voorbeelden van WinUI-besturingselementen en -functies. Haal de app op uit de Microsoft Store of blader door de broncode op GitHub.

Note

IXamlConditionvervangt de IXamlPredicate interface van experimentele releases van de Windows App SDK 2.0.

Een voorwaarde implementeren

Als u een voorwaarde wilt maken, definieert u een klasse die is afgeleid van DependencyObject en IXamlCondition implementeert. De XAML-parser roept de methode Evaluate aan en geeft de tekst door tussen de haakjes van de declaratie van de voorwaardelijke naamruimte als de argument parameter. Retourneer true om de gekwalificeerde markup op te nemen of false om deze te negeren.

In dit voorbeeld uit het voorbeeld van de WinUI 3 Gallery worden featureflags geëvalueerd die de app in een dictionary opslaat:

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

Een voorwaardelijke namespace declareren

Wijs eerst de naamruimte toe die uw voorwaardeklasse bevat met behulp van een using: declaratie. Na het ? scheidingsteken van een voorwaardelijke naamruimte verwijst u vervolgens naar de klasse via dat voorvoegsel en geeft u het argument tussen haakjes door:

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

In dit voorbeeld roept de parser Evaluate("NewExperience") aan voor markeringen die gebruikmaken van het newExp voorvoegsel en Evaluate("LegacyMode") voor markeringen die gebruikmaken van het legacy voorvoegsel.

De voorwaarde gebruiken voor elementen, kenmerken en setters

Gebruik het voorwaardelijke voorvoegsel op dezelfde manier als u de ingebouwde voorwaardelijke naamruimten gebruikt. Deze voorbeelden zijn gebaseerd op het WinUI 3 Gallery-voorbeeld.

Als u een element alleen wilt opnemen wanneer een voorwaarde is true, plaatst u ervoor:

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

Als u een eigenschap alleen wilt instellen wanneer een voorwaarde is true, moet u het kenmerk laten voorafgaan door:

<!-- 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" />

Als u een stijlsetter alleen wilt toepassen wanneer een voorwaarde true is, moet u het element Setter vooraf laten gaan door:

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

De status instellen voordat de XAML wordt geparseerd

De parser slaat het resultaat van Evaluate voor elke combinatie van voorwaarde en argument voor de levensduur van het proces in de cache op. Als u de status wijzigt die door een voorwaarde wordt gelezen nadat het resultaat in de cache is opgeslagen, wordt markup die al is geparseerd niet gewijzigd en gebruikt markup die later wordt geparseerd nog steeds het resultaat uit de cache. Als u een andere waarde wilt gebruiken, start u de app opnieuw.

Stel de status in die uw voorwaarde leest voordat de parser deze evalueert, bijvoorbeeld bij het opstarten van de app of voordat u InitializeComponent aanroept in een paginaconstructor:

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

  • Twee elementen kunnen niet hetzelfde x:Namehebben, zelfs niet als slechts één van deze elementen tijdens runtime is opgenomen.
  • Als u meer dan één voorwaarde toepast op hetzelfde kenmerk, moet u ervoor zorgen dat slechts één daarvan tijdens runtime naar true evalueert. Als meer dan één expressie resulteert in true, genereert de parser een uitzondering.
  • Omdat voorwaarden tijdens runtime worden geëvalueerd, kan de XAML-compiler deze niet controleren op logische consistentie. Test elke combinatie van voorwaardewaarden die door uw app worden ondersteund.
  • Aangepaste voorwaarden werken niet met items uit de x: naamruimte (http://schemas.microsoft.com/winfx/2006/xaml), zoals x:Uid en x:Key.