{ThemeResource} 标记扩展{ThemeResource} markup extension

使用根据当前处于活动状态的主题检索不同资源的附加系统逻辑,通过计算对某个资源的引用来为任何 XAML 属性提供值。Provides a value for any XAML attribute by evaluating a reference to a resource, with additional system logic that retrieves different resources depending on the currently active theme. {StaticResource} 标记扩展类似,资源在 ResourceDictionary 中定义,并且 ThemeResource 用法引用 ResourceDictionary 中的该资源的键。Similar to {StaticResource} markup extension, resources are defined in a ResourceDictionary, and a ThemeResource usage references the key of that resource in the ResourceDictionary.

XAML 属性使用方法XAML attribute usage

<object property="{ThemeResource key}" .../>

XAML 值XAML values

术语Term 描述Description
key 所请求资源的键。The key for the requested resource. 此键最初通过 ResourceDictionary 分配。This key is initially assigned by the ResourceDictionary. 资源键可以是以 XamlName 语法定义的任何字符串。A resource key can be any string defined in the XamlName Grammar.

备注Remarks

ThemeResource 是用于获取在 XAML 资源字典中的其他地方定义的 XAML 属性值的技术。A ThemeResource is a technique for obtaining values for a XAML attribute that are defined elsewhere in a XAML resource dictionary. 该标记扩展提供与 {StaticResource} 标记扩展相同的基本用途。The markup extension serves the same basic purpose as the {StaticResource} markup extension. 与 {StaticResource} 标记扩展的行为差异在于 ThemeResource 引用可以根据系统当前在使用哪个主题动态使用不同的字典作为主要查找位置。The difference in behavior versus {StaticResource} markup extension is that a ThemeResource reference can dynamically use different dictionaries as the primary lookup location, depending on which theme is currently being used by the system.

首次启动应用时,将根据启动时正在使用的主题对由 ThemeResource 引用执行的任何资源引用进行计算。When the app first starts, any resource reference made by a ThemeResource reference is evaluated based on the theme in use at startup. 但是,如果用户之后在运行时更改了活动主题,则系统将重新计算每个 ThemeResource 引用、检索可能不同的特定于主题的资源,并在可视化树中所有合适的位置使用新的资源值重新显示应用。But if the user subsequently changes the active theme at run-time, the system will re-evaluate every ThemeResource reference, retrieve a theme-specific resource that may be different, and redisplay the app with new resource values in all appropriate places in the visual tree. StaticResource 在 XAML 加载时/应用启动时确定,并且在运行时不会重新计算。A StaticResource is determined at XAML load time / app startup and won't be re-evaluated at run-time. (还有可以动态重新加载 XAML 的其他技术,例如可视状态,但是这些技术在比由 {StaticResource} 标记扩展启用的基本资源计算更高的级别上操作)。(There are other techniques such as visual states that reload XAML dynamically, but those techniques operate at a higher level that the basic resource evaluation enabled by {StaticResource} markup extension).

ThemeResource 接受一个参数,该参数指定所请求的资源的键。ThemeResource takes one argument, which specifies the key for the requested resource. 在 Windows 运行时 XAML 中,资源键始终是一个字符串。A resource key is always a string in Windows Runtime XAML. 有关最初如何指定资源键的详细信息,请参阅 x:Key 属性For more info on how the resource key is initially specified, see x:Key attribute.

有关如何定义资源和正确使用 ResourceDictionary 的详细信息(包括示例代码),请参阅 ResourceDictionary 和 XAML 资源引用For more info on how to define resources and properly use a ResourceDictionary, including sample code, see ResourceDictionary and XAML resource references.

重要提示StaticResource 一样,ThemeResource 不应当尝试对在 XAML 文件中定义的在字典顺序上位于更靠后位置的资源进行前向引用。Important As with StaticResource, a ThemeResource must not attempt to make a forward reference to a resource that is defined lexically further within the XAML file. 这样的尝试不受支持。Attempting to do so is not supported. 即使前向引用没有失败,尝试进行这样的引用也会对性能造成不利影响。Even if the forward reference doesn't fail, trying to make one carries a performance penalty. 为实现最佳效果,请调整你的资源字典的组成,以避免使用前向引用。For best results, adjust the composition of your resource dictionaries so that forward references are avoided.

尝试为无法解析的键指定 ThemeResource 会在运行时引发 XAML 分析异常。Attempting to specify a ThemeResource to a key that cannot resolve throws a XAML parse exception at run time. 设计工具还可能会提供警告或错误。Design tools may also offer warnings or errors.

在 Windows 运行时 XAML 处理器实现中,没有针对 ThemeResource 的后备类表示。In the Windows Runtime XAML processor implementation, there is no backing class representation for ThemeResource. 在代码中最接近的等效体是使用 ResourceDictionary 的集合 API,例如调用 ContainsTryGetValueThe closest equivalent in code is to use the collection API of a ResourceDictionary, for example calling Contains or TryGetValue.

ThemeResource 是一个标记扩展。ThemeResource is a markup extension. 当需要将属性值转义为除文字值或处理程序名称之外的值时,以及当需求更具全局性而不是仅仅将类型转换器放在某些类型或属性上时,通常需要实现标记扩展。Markup extensions are typically implemented when there is a requirement to escape attribute values to be other than literal values or handler names, and the requirement is more global than just putting type converters on certain types or properties. XAML 中的所有标记扩展在其属性语法中都使用“{”和“}”字符,通过此约定,XAML 处理器可以知道标记扩展必须处理属性。All markup extensions in XAML use the "{" and "}" characters in their attribute syntax, which is the convention by which a XAML processor recognizes that a markup extension must process the attribute.

何时以及如何使用 {ThemeResource} 而不是 {StaticResource}When and how to use {ThemeResource} rather than {StaticResource}

ThemeResource 解析为资源字典中的项时所遵循的规则通常与 StaticResource 相同。The rules by which a ThemeResource resolves to an item in a resource dictionary are generally the same as StaticResource. ThemeResource 查找可以扩展到 ThemeDictionaries 集合中引用的 ResourceDictionary 文件,但 StaticResource 也可以这样做。A ThemeResource lookup can extend into the ResourceDictionary files that are referenced in a ThemeDictionaries collection, but a StaticResource can do that also. 区别是 ThemeResource 在运行时可以重新计算,而 StaticResource 不能。The difference is that a ThemeResource can re-evaluate at run-time and a StaticResource can't.

无论哪个主题处于活动状态,每个主题字典中的键集都应当提供相同的键控资源集。The set of keys in each theme dictionary should provide the same set of keyed resources no matter which theme is active. 如果某个给定的键控资源存在于 HighContrast 主题字典中,则 LightDefault 中也应当存在具有该名称的另一资源。If a given keyed resource exists in the HighContrast theme dictionary, then another resource with that name should also exist in Light and Default. 如果不是这样,则当用户切换主题时资源查找可能会失败,并且你的应用看起来将不正常。If that isn't true, resource lookup might fail when the user switches themes and your app won't look right. 但是,主题字典可以包含仅从同一范围内引用的键控资源来提供子值;这些不需要在所有主题中都等效。It is possible though that a theme dictionary can contain keyed resources that are only referenced from within the same scope to provide sub-values; these don't need to be equivalent in all themes.

通常,只有当这些值可以在主题之间更改时或者受更改的值支持时,你才应当将资源放置在主题字典中并使用 ThemeResource 引用这些资源。In general you should place resources in theme dictionaries and make references to those resources using ThemeResource only when those values can change between themes or are supported by values that change. 这适合以下类型的资源:This is appropriate for these kinds of resources:

  • 画笔,特别是用于 SolidColorBrush 的颜色。Brushes, in particular colors for SolidColorBrush. 在默认的 XAML 控件模板 (generic.xaml) 中,这大约占 ThemeResource 使用情况的 80%。These make up about 80% of the ThemeResource usages in the default XAML control templates (generic.xaml).
  • 用于边框、偏移、边距和填充等的像素值。Pixel values for borders, offsets, margin and padding and so on.
  • 字体属性,例如 FontFamilyFontSizeFont properties such as FontFamily or FontSize.
  • 用于有限数目的控件的完整模板,这些控件通常是系统样式的并且用于动态展示,例如 GridViewItemListViewItemComplete templates for a limited number of controls that are usually system-styled and used for dynamic presentation, like GridViewItem and ListViewItem.
  • 文本显示样式(通常更改字体颜色、背景,还可能更改大小)。Text display styles (usually to change font color, background, and possibly size).

Windows 运行时提供了专门由 ThemeResource 引用的资源集。The Windows Runtime provides a set of resources that are specifically intended to be referenced by ThemeResource. 这些资源将全部作为 XAML 文件 themeresources.xaml 的一部分列出,该文件在包含于 Windows 软件开发工具包 (SDK) 的 include/winrt/xaml/design 文件夹中提供。These are all listed as part of the XAML file themeresources.xaml, which is available in the include/winrt/xaml/design folder as part of the Windows Software Development Kit (SDK). 有关在 themeresources.xaml 中定义的主题画笔和其他样式的文档,请参阅 XAML 主题资源For documentation on the theme brushes and additional styles that are defined in themeresources.xaml, see XAML theme resources. 画笔将在表格中记录,该表格将告知你,针对三个可能活动的主题,其中每个画笔将具有哪些颜色值。The brushes are documented in a table that tells you what color value each brush has for each of the three possible active themes.

每当存在可能会因主题更改而更改的基础资源时,控件模板中的可视状态的 XAML 定义都应当使用 ThemeResource 引用。The XAML definitions of visual states in a control template should use ThemeResource references whenever there's an underlying resource that might change because of a theme change. 系统主题更改通常也不会导致可视状态更改。A system theme change won't typically also cause a visual state change. 在这种情况下,资源需要使用 ThemeResource 引用,以便可以为仍然处于活动状态的可视状态重新计算值。The resources need to use ThemeResource references in this case so that values can be re-evaluated for the still-active visual state. 例如,如果你具有更改特定 UI 部件的画笔颜色及其属性之一的可视状态,并且该画笔颜色对于每个主题是不同的,则你应当使用 ThemeResource 引用在默认模板中提供该属性的值以及对该默认模板进行任何可视状态修改。For example, if you have a visual state that changes a brush color of a particular UI part and one of its properties, and that brush color is different per-theme, you should use a ThemeResource reference for providing that property's value in the default template and also any visual state modification to that default template.

可能会在一系列具有依赖关系的值中看到 ThemeResource 用法。ThemeResource usages might be seen in a series of dependent values. 例如,由同时还是键控资源的 SolidColorBrush 使用的 Color值可能会使用 ThemeResource 引用。For example, a Color value used by a SolidColorBrush that is also a keyed resource might use a ThemeResource reference. 但是,任何使用键控 SolidColorBrush 资源的 UI 属性也将使用 ThemeResource 引用,以便每个启用了动态值的 Brush 类型属性在主题更改时会随之更改。But any UI properties that use the keyed SolidColorBrush resource would also use a ThemeResource reference, so that it's specifically each Brush-type property that's enabling a dynamic value change when the theme changes.

请注意  {ThemeResource}和主题切换运行时资源评估是在 Windows 8.1 XAML 中受支持但不是支持在 XAML 中面向 Windows 8 应用程序。Note  {ThemeResource} and run-time resource evaluation on theme switching is supported in Windows 8.1 XAML but not supported in XAML for apps targeting Windows 8.

系统资源System resources

某些主题资源引用系统资源值作为基础子值。Some theme resources reference system resource values as an underlying sub-value. 系统资源是不存在于任何 XAML 资源字典中的特殊资源值。A system resource is a special resource value that isn't found in any XAML resource dictionary. 这些值依赖于 Windows 运行时 XAML 支持中的行为转发来自系统本身的值,并以 XAML 资源可以引用的形式表示它们。These values rely on behavior in Windows Runtime XAML support to forward values from the system itself, and represent them in a form that a XAML resource can reference. 例如,有一个名为“SystemColorButtonFaceColor”的系统资源,它提供了一种 RGB 颜色。For example, there is a system resource named "SystemColorButtonFaceColor" that represents an RGB color. 此颜色来自非仅特定于 Windows 运行时和 Windows 运行时应用的系统颜色和主题的外表。This color comes from the aspects of system colors and themes that aren't just specific to Windows Runtime and Windows Runtime apps.

系统资源通常是某个高对比度主题的基础值。System resources are often the underlying values for a high-contrast theme. 用户可以控制其高对比度主题的颜色选择,并且用户使用同样非特定于 Windows 运行时应用的系统功能执行这些选择。The user is in control of the color choices for their high-contrast theme, and the user makes these choices using system features that also aren't specific to Windows Runtime apps. 通过将系统资源引用为 ThemeResource 引用,Windows 运行时应用的高对比度主题的默认行为可以使用这些由用户控制的且由系统公开的特定于主题的值。By referencing the system resources as ThemeResource references, the default behavior of the high-contrast themes for Windows Runtime apps can use these theme-specific values that are controlled by the user and exposed by the system. 另外,这些引用现在已标记为当系统检测到运行时主题更改时进行重新计算。Also, the references are now marked for re-evaluation if the system detects a run-time theme change.

示例 {ThemeResource} 用法An example {ThemeResource} usage

下面是摘自默认的 generic.xaml 和 themeresources.xaml 文件的某个示例 XAML,它展示了如何使用 ThemeResourceHere's some example XAML taken from the default generic.xaml and themeresources.xaml files to illustrate how to use ThemeResource. 我们将只查看一个模板(默认的 Button)并了解如何将两个属性(BackgroundForeground)声明为对主题更改做出响应。We'll look at just one template (the default Button) and how two properties are declared (Background and Foreground) to be responsive to theme changes.

    <!-- 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 引用名为 ButtonBackgroundThemeBrushButtonForegroundThemeBrushSolidColorBrush 资源。Here, the properties take a Brush value, and the reference to SolidColorBrush resources named ButtonBackgroundThemeBrush and ButtonForegroundThemeBrush are made using ThemeResource.

Button 的某些可视状态也调整这些相同的属性。These same properties are also adjusted by some of the visual states for a Button. 值得注意的是,当单击某个按钮时,背景颜色会更改。Notably, the background color changes when a button is clicked. 另外,可视状态情节提要中的 BackgroundForeground 动画使用 DiscreteObjectKeyFrame 对象和对以 ThemeResource 作为关键帧值的画笔的引用。Here too, the Background and Foreground animations in the visual state storyboard use DiscreteObjectKeyFrame objects and references to brushes with ThemeResource as the key frame value.

<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 前向引用。Each of these brushes is defined earlier in generic.xaml: they had to be defined prior to any templates using them to avoid XAML forward references. 下面是针对“Default”主题字典的定义。Here's those definitions, for the "Default" theme dictionary.

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

然后,每个其他主题字典也定义了这些画笔,例如:Then each of the other theme dictionaries also has these brushes defined, for example:

        <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 引用。Here the Color value is another ThemeResource reference to a system resource. 如果你引用了某个系统资源,并且希望它发生更改以响应主题更改,则应当使用 ThemeResource 进行该引用。If you reference a system resource, and you want it to change in response to a theme change, you should use ThemeResource to make the reference.

Windows 8 行为Windows 8 behavior

不支持 Windows 8 ThemeResource标记扩展,它是从 Windows 8.1 开始提供。Windows 8 did not support the ThemeResource markup extension, it is available starting with Windows 8.1. 此外,Windows 8 不支持动态切换的 Windows 运行时应用的主题相关资源。Also, Windows 8 did not support dynamically switching the theme-related resources for a Windows Runtime app. 必须重新启动应用,才能应用针对 XAML 模板和样式的主题更改。The app had to be restarted in order to pick up the theme change for the XAML templates and styles. 这不是良好的用户体验,因此应用程序,强烈建议,若要重新编译和面向 Windows 8.1,以便他们可以使用与样式ThemeResource用法和动态切换主题时用户执行的操作。This isn't a good user experience, so apps are strongly encouraged to recompile and target Windows 8.1 so that they can use styles with ThemeResource usages and can dynamically switch themes when the user does. Windows 8,但运行 Windows 8.1 上继续使用 Windows 8 行为已编译的应用程序。Apps that were compiled for Windows 8 but running on Windows 8.1 continue to use the Windows 8 behavior.

设计时工具支持 {ThemeResource} 标记扩展Design-time tools support for the {ThemeResource} markup extension

Microsoft Visual Studio 2013 可以包括可能的键值在 Microsoft IntelliSense 下拉列表中使用时 {ThemeResource} XAML 页面中的标记扩展。Microsoft Visual Studio 2013 can include possible key values in the Microsoft IntelliSense dropdowns when you use the {ThemeResource} markup extension in a XAML page. 例如,键入“{ThemeResource”时会立即显示来自 XAML 主题资源的任何资源键。For example, as soon as you type "{ThemeResource", any of the resource keys from the XAML theme resources are displayed.

在资源键作为任何 {ThemeResource} 用法的一部分存在后,转到定义 (F12) 功能可以解析该资源并向你显示设计时 generic.xaml、定义主题资源的位置。Once a resource key exists as part of any {ThemeResource} usage, the Go To Definition (F12) feature can resolve that resource and show you the generic.xaml for design time, where the theme resource is defined. 由于多次定义了主题资源(每个主题),“转到定义” 会将你转到文件中找到的第一个定义(Default 的定义)。Because theme resources are defined more than once (per-theme) Go To Definition takes you to the first definition found in the file, which is the definition for Default. 如果你需要其他定义,可以在该文件中搜索键名并找到其他主题的定义。If you want the other definitions you can search for the key name within the file and find the other themes' definitions.