通过评估资源引用为任何 XAML 属性提供值,并采用附加的系统逻辑,根据当前活动主题检索不同的资源。 与 {StaticResource} 标记扩展类似,资源在 ResourceDictionary 中定义, ThemeResource 用法引用 ResourceDictionary 中该资源的键。
XAML 属性用法
<object property="{ThemeResource key}" .../>
XAML 值
| 术语 | Description |
|---|---|
| 关键值 | 所请求资源的密钥。 此密钥最初由 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 查找可以扩展到ResourceDictionary 文件,这些文件在 ThemeDictionaries 集合中被引用,但 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 引用,因此正是每个 画笔类型属性在主题变更时启用动态值更改。
注意{ThemeResource} Windows 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 进行引用。
{ThemeResource} 标记扩展的设计时工具支持
在 XAML 页面中使用 {ThemeResource} 标记扩展时,Microsoft Visual Studio 可以在 Microsoft IntelliSense 下拉列表中包含可能的键值。 例如,键入“{ThemeResource”后, 就会显示 XAML 主题资源 中的任何资源键。
资源键作为任何 {ThemeResource} 用法的一部分存在后, Go To Definition (F12) 功能可以解析该资源,并在设计时向你显示 generic.xaml,其中定义了主题资源。 因为主题资源定义多次(每主题) 转到定义 会将你转到文件中找到的第一个定义,这是 默认的定义。 如果需要其他定义,可以搜索文件中的键名称,并查找其他主题的定义。