条件 XAML 提供直接在 XAML 标记中使用 ApiInformation.IsApiContractPresent 方法的方法。 可以基于 OS 级 API 协定的存在设置属性,而无需在后面编写代码。 条件语句在运行时进行求值——带有条件 XAML 标记的元素如果其求值结果为 true,则会被解析;否则会被忽略。
条件 XAML 需要Windows 10版本 1809(内部版本 17763)或更高版本,这是Windows 应用 SDK应用的最低操作系统版本。
先决条件
- Windows 应用 SDK项目。 有关设置步骤,请参阅 创建第一个 WinUI 3 应用。
- 熟悉 版本自适应应用 和
ApiInformation类。
Important
条件 XAML 使用ApiInformation方法,用于检查 OS 提供的Windows 运行时 (Windows.*) API 协定和类型是否存在。 这些检查不适用于 WinUI 3 (Microsoft.UI.Xaml.*) 控件,因为 WinUI 3 通过Windows 应用 SDK而不是 OS 随应用一起提供,因此,无论设备运行的Windows 10/11 版本如何,构建应用时都会始终存在每个 WinUI 3 控件。
#if预处理器指令在这里也帮不上忙:它们是在编译时根据目标框架来求值的,而不是在运行时根据操作系统或实际安装的 Windows 应用 SDK 版本来求值。 若要根据应用当前针对的 Windows 应用 SDK 版本来控制某项功能是否启用,请在构建时检查 SDK 版本,或在 API 调用外使用 try/catch。 有关详细信息,请参阅 版本自适应代码 。
有关 ApiInformation 和 API 合约的背景信息,请参阅 版本自适应应用。
条件命名空间
若要在 XAML 中使用条件方法,请在页面顶部声明条件 XAML 命名空间 :
xmlns:myNamespace="schema?conditionalMethod(parameter)"
分隔符前 ? 的内容是命名空间或架构。
? 后面的内容是用于确定命名空间的求值结果是 true 还是 false 的条件方法。
在大多数情况下,架构是默认的 XAML 命名空间:
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
条件 XAML 支持以下条件方法:
| 方法 | 逆 |
|---|---|
IsApiContractPresent(ContractName, VersionNumber) |
IsApiContractNotPresent(ContractName, VersionNumber) |
IsTypePresent(ControlType) |
IsTypeNotPresent(ControlType) |
IsPropertyPresent(ControlType, PropertyName) |
IsPropertyNotPresent(ControlType, PropertyName) |
注释
使用 IsApiContractPresent 和 IsApiContractNotPresent 可获得最佳设计时体验。 在 Visual Studio 设计器中,其他条件语句尚未获得完全支持。
有条件地设置属性
此示例仅在应用运行于 Windows 10 版本 1903(2019 年 5 月更新,内部版本 18362)或更高版本时,才会在 TextBlock 中显示文本——这种合约检查是有意义的,因为它比 Windows 应用 SDK 的 1809 最低版本要求更新。
首先,定义条件命名空间:
xmlns:contract8Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,8)"
然后,使用条件命名空间为属性添加前缀:
<TextBlock contract8Present:Text="Hello, Conditional XAML"/>
下面是完整的标记代码:
<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>
后台代码中的等效检查:
TextBlock textBlock = new TextBlock();
if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
{
textBlock.Text = "Hello, Conditional XAML";
}
注释
即使 IsApiContractPresent 将字符串用作协定名称参数,在 XAML 命名空间声明中也不要将其用引号括起来。
由于 Windows 应用 SDK 支持的最低操作系统版本是 1809(UniversalApiContract版本 7),因此在 Windows 应用 SDK 应用中检查协定版本是否小于或等于 7,结果始终为 true,无法提供任何有用信息。 仅检查 大于 7 的协定版本。
使用 if/else 条件
若要根据 API 协定设置不同的值,请同时定义正条件命名空间和负条件命名空间:
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)"
然后设置属性两次,每个属性具有不同的条件前缀。 运行时仅应用一个:
<TextBlock contract8NotPresent:Text="Hello, World"
contract8Present:Text="Hello, May 2019 Update or later"/>
按条件实例化控件
注释
根据 OS API 协定(而不是有条件地设置属性)实例化元素是特定于 UWP 的模式。 它不适用于 WinUI 3 控件。
在 UWP 中,当较新的控件在 OS 上不可用时,可以使用此模式回退到较旧的 Windows.UI.Xaml.Controls 控件。 在Windows 应用 SDK应用中,WinUI 3 控件(Microsoft.UI.Xaml.Controls.*)通过Windows 应用 SDK(而不是 OS)随应用一起提供。 应用构建的每个控件(包括 ColorPicker )都保证在运行时存在,因此在实例化之前,无需检查操作系统版本。
如果需要根据应用所针对的 Windows 应用 SDK 版本来限制 WinUI 3 控件或 API 的使用,请在构建时进行该检查(通过将最低 Windows 应用 SDK 包版本设为目标版本),或者将运行时调用包装在 try/catch 中,而不要使用条件 XAML。