{ThemeResource} 标记扩展
通过评估对资源的引用来提供任何 XAML 属性的值,以及根据当前活动主题检索不同资源的其他系统逻辑。 与 {StaticResource} 标记扩展类似,资源在 ResourceDictionary 中定义,ThemeResource 用法引用 ResourceDictionary 中该资源的键。
XAML 属性使用方法
<object property="{ThemeResource key}" .../>
XAML 值
术语 | 说明 |
---|---|
键 | 所请求资源的密钥。 此密钥最初由 ResourceDictionary 分配。 资源键可以是以 XamlName 语法定义的任何字符串。 |
注解
ThemeResource 是一种用于获取 XAML 属性的值的技术,该属性在 XAML 资源字典中的其他位置定义。 标记扩展与 {StaticResource} 标记扩展具有相同的基本用途。 行为与 {StaticResource} 标记扩展的区别在于 ,ThemeResource 引用可以动态使用不同的字典作为主要查找位置,具体取决于系统当前正在使用的主题。
首次启动应用时,将根据启动时使用的主题评估 ThemeResource 引用所做的任何资源引用。 但是,如果用户随后在运行时更改活动主题,系统将重新评估每个 ThemeResource 引用,检索可能不同的主题特定资源,并在可视化树的所有适当位置使用新的资源值重新显示应用。 StaticResource 在 XAML 加载时间/应用启动时确定,不会在运行时重新评估。 (还有其他技术(如视觉状态)动态重载 XAML,但这些技术在更高级别运行,即基本资源评估已启用 {StaticResource} 标记扩展)。
ThemeResource 采用一个参数,该参数指定所请求资源的键。 资源键始终是Windows 运行时 XAML 中的字符串。 有关如何最初指定资源密钥的详细信息,请参阅 x:Key 属性。
有关如何定义资源并正确使用 ResourceDictionary(包括示例代码)的详细信息,请参阅 ResourceDictionary 和 XAML 资源引用。
与 StaticResource 一样,ThemeResource 不得尝试对 XAML 文件中进一步定义的资源的转发引用。 不支持尝试这样做。 即使前向引用没有失败,也尝试使一个引用会受到性能损失。 为获得最佳结果,请调整资源字典的构成,以避免转发引用。
尝试将 ThemeResource 指定为无法在运行时引发 XAML 分析异常的键。 设计工具也可能提供警告或错误。
在Windows 运行时 XAML 处理器实现中,ThemeResource 没有支持类表示形式。 代码中最接近的等效项是使用 ResourceDictionary 的集合 API,例如调用 Contains 或 *TryGetValue。
ThemeResource 是标记扩展。 当要求转义特性值应为非文本值或非处理程序名称时,通常会实现标记扩展,相对于只在某些类型或属性上放置类型转换器而言,此需求更具有全局性。 XAML 中的所有标记扩展在其属性语法中都使用“{”和“}”字符,通过此约定,XAML 处理器可以知道标记扩展必须处理属性。
何时以及如何使用 {ThemeResource} 而不是 {StaticResource}
ThemeResource 解析为资源字典中的项的规则通常与 StaticResource 相同。 ThemeResource 查找可以扩展到在 ThemeDictionaries 集合中引用的 ResourceDictionary 文件,但 StaticResource 也可以执行此操作。 区别在于 ThemeResource 可以在运行时重新评估, StaticResource 无法重新评估。
无论哪个主题处于活动状态,每个主题字典中的键集都应提供相同的键键资源集。 如果 HighContrast 主题字典中存在给定的键式资源,则具有该名称的另一个资源也应存在于 Light 和 Default 中。 如果这不是真的,当用户切换主题和应用看起来不正确时,资源查找可能会失败。 不过,主题字典可以包含仅从同一范围内引用的键式资源来提供子值;这些不需要在所有主题中等效。
一般情况下,应将资源放在主题字典中,仅当这些值可以在主题之间更改或由更改的值支持时,才使用 ThemeResource 对这些资源进行引用。 这适用于以下类型的资源:
- 画笔,尤其是 SolidColorBrush 的颜色。 它们约占默认 XAML 控件模板(generic.xaml)中 ThemeResource 使用情况的 80%。
- 边框、偏移量、边距和填充等的像素值。
- FontFamily 或 FontSize 等字体属性。
- 用于通常采用系统样式并用于动态呈现的有限数量的控件的完整模板,例如 GridViewItem 和 ListViewItem。
- 文本显示样式(通常更改字体颜色、背景和可能的大小)。
Windows 运行时提供了一组专门供 ThemeResource 引用的资源。 这些都作为 XAML 文件 themeresources.xaml 的一部分列出,该主题在 Windows 软件开发工具包(SDK)的 include/winrt/xaml/design 文件夹中提供。 有关主题画笔和在 themeresources.xaml 中定义的其他样式的文档,请参阅 XAML 主题资源。 画笔记录在表中,告知每个画笔针对三个可能的活动主题中每个画笔具有的颜色值。
控件模板中视觉状态的 XAML 定义应使用 ThemeResource 引用,只要存在可能因为主题更改而发生更改的基础资源。 系统主题更改通常不会导致视觉状态更改。 在这种情况下,资源需要使用 ThemeResource 引用,以便可以重新评估仍处于活动状态的视觉状态的值。 例如,如果你有一个视觉状态,该视觉状态更改特定 UI 部件的画笔颜色及其属性之一,并且画笔颜色是不同的每个主题,则应使用 ThemeResource 引用在默认模板中提供该属性的值,以及该默认模板的任何视觉状态修改。
主题资源 用法可能在一系列依赖值中看到。 例如,SolidColorBrush 使用的 Color 值(也是键式资源)可能使用 ThemeResource 引用。 但是,使用键式 SolidColorBrush 资源的任何 UI 属性也将使用 ThemeResource 引用,以便它是在主题更改时启用动态值更改的每个 画笔类型属性。
Windows{ThemeResource}
8.1 XAML 支持主题切换上的运行时资源评估,但在面向 Windows 8 的应用的 XAML 中不受支持。
系统资源
某些主题资源引用系统资源值作为基础子值。 系统资源是任何 XAML 资源字典中未找到的特殊资源值。 这些值依赖于Windows 运行时 XAML 支持中的行为来转发系统本身的值,并用 XAML 资源可以引用的形式表示这些值。 例如,有一个名为“SystemColorButtonFaceColor”的系统资源表示 RGB 颜色。 这种颜色来自特定于Windows 运行时和Windows 运行时应用的系统颜色和主题的各个方面。
系统资源通常是高对比度主题的基础值。 用户控制其高对比度主题的颜色选择,并且用户使用系统功能做出这些选择,这些功能也不适用于Windows 运行时应用。 通过将系统资源引用称为 ThemeResource 引用,Windows 运行时应用的高对比度主题的默认行为可以使用由用户控制并由系统公开的这些特定于主题的值。 此外,如果系统检测到运行时主题更改,则引用现在将标记为重新评估。
示例 {ThemeResource} 用法
下面是从默认 generic.xaml 和 themeresources.xaml 文件中获取的一些示例 XAML,演示如何使用 ThemeResource。 我们将只查看一个模板(默认按钮),以及如何声明两个属性(背景和前台)以响应主题更改。
<!-- Default style for Windows.UI.Xaml.Controls.Button -->
<Style TargetType="Button">
<Setter Property="Background" Value="{ThemeResource ButtonBackgroundThemeBrush}" />
<Setter Property="Foreground" Value="{ThemeResource ButtonForegroundThemeBrush}"/>
...
此处,属性采用 Brush 值,并使用 ThemeResource 命名ButtonBackgroundThemeBrush
并ButtonForegroundThemeBrush
生成对 SolidColorBrush 资源的引用。
这些相同的属性也由按钮的一些视觉状态进行调整。 值得注意的是,单击按钮时背景色会发生变化。 在这里,视觉状态情节提要中的背景动画和前景动画使用 DiscreteObjectKeyFrame 对象和对使用 ThemeResource 作为关键帧值的画笔的引用。
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonPressedBackgroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonPressedForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
上述每个画笔在 generic.xaml 中之前定义:必须在使用它们的任何模板之前定义这些画笔以避免 XAML 转发引用。 下面是“默认”主题字典的这些定义。
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
...
<SolidColorBrush x:Key="ButtonBackgroundThemeBrush" Color="Transparent" />
<SolidColorBrush x:Key="ButtonForegroundThemeBrush" Color="#FFFFFFFF" />
...
<SolidColorBrush x:Key="ButtonPressedBackgroundThemeBrush" Color="#FFFFFFFF" />
<SolidColorBrush x:Key="ButtonPressedForegroundThemeBrush" Color="#FF000000" />
...
然后,其他每个主题字典还定义了这些画笔,例如:
<ResourceDictionary x:Key="HighContrast">
<!-- High Contrast theme resources -->
...
<SolidColorBrush x:Key="ButtonBackgroundThemeBrush" Color="{ThemeResource SystemColorButtonFaceColor}" />
<SolidColorBrush x:Key="ButtonForegroundThemeBrush" Color="{ThemeResource SystemColorButtonTextColor}" />
...
<SolidColorBrush x:Key="ButtonPressedBackgroundThemeBrush" Color="{ThemeResource SystemColorButtonTextColor}" />
<SolidColorBrush x:Key="ButtonPressedForegroundThemeBrush" Color="{ThemeResource SystemColorButtonFaceColor}" />
此处的 Color 值是对系统资源的另一个 ThemeResource 引用。 如果引用系统资源,并且希望它更改以响应主题更改,则应使用 ThemeResource 进行引用。
Windows 8 行为
Windows 8 不支持 ThemeResource 标记扩展,从 Windows 8.1 开始可用。 此外,Windows 8 不支持为Windows 运行时应用动态切换与主题相关的资源。 必须重启应用才能选取 XAML 模板和样式的主题更改。 这不是良好的用户体验,因此强烈建议应用重新编译并面向 Windows 8.1,以便他们可以将样式与 ThemeResource 用法一起使用,并在用户这样做时动态切换主题。 已针对 Windows 8 编译但运行在 Windows 8.1 上的应用继续使用 Windows 8 行为。
{ThemeResource} 标记扩展的设计时工具支持
Microsoft Visual Studio 2013 在 XAML 页面中使用 {ThemeResource} 标记扩展时,可以在 Microsoft IntelliSense 下拉列表中包含可能的键值。 例如,键入“{ThemeResource”后,就会显示 XAML 主题资源中的任何资源键。
资源键作为任何 {ThemeResource} 用法的一部分存在后, Go To Definition (F12) 功能可以解析该资源,并在设计时向你显示 generic.xaml,其中定义了主题资源。 因为主题资源定义多次(每主题)转到定义会将你转到文件中找到的第一个定义,这是默认的定义。 如果需要其他定义,可以搜索文件中的键名称,并查找其他主题的定义。