XAML 样式XAML styles

可以使用 XAML 框架通过多种方式自定义应用的外观。You can customize the appearance of your apps in many ways by using the XAML framework. 通过样式可以设置控件属性,并重复使用这些设置,以便保持多个控件具有一致的外观。Styles let you set control properties and reuse those settings for a consistent appearance across multiple controls.

样式基础知识Style basics

使用样式可将属性设置提取到可重复使用的资源中。Use styles to extract visual property settings into reusable resources. 下面的示例显示了具有设置 BorderBrushBorderThicknessForeground 属性样式的 3 个按钮。Here's an example that shows 3 buttons with a style that sets the BorderBrush, BorderThickness and Foreground properties. 通过应用样式可以使控件具有相同外观,而无需单独为每个控件设置这些属性。By applying a style, you can make the controls appear the same without having to set these properties on each control separately.

通过样式设计的按钮

你可以定义在 XAML 中为控件嵌入的样式,或者作为可重复使用的资源。You can define a style inline in the XAML for a control, or as a reusable resource. 在单个页面的 XAML 文件中、App.xaml 文件中,或者单独的资源词典 XAML 文件中定义资源。Define resources in an individual page's XAML file, in the App.xaml file, or in a separate resource dictionary XAML file. 可以在应用之间共享资源词典 XAML 文件,并且可以将多个资源词典合并到单个应用中。A resource dictionary XAML file can be shared across apps, and more than one resource dictionary can be merged in a single app. 定义资源的位置决定了该资源可以使用的范围。Where the resource is defined determines the scope in which it can be used. 页面级资源只在定义了它们的页面中可用。Page-level resources are available only in the page where they are defined. 如果在 App.xaml 和页面中同时定义了具有相同关键字的资源,则页面中的资源将覆盖 App.xaml 中的资源。If resources with the same key are defined in both App.xaml and in a page, the resource in the page overrides the resource in App.xaml. 如果资源在单独的资源词典文件中定义,则它的范围由引用资源词典的位置确定。If a resource is defined in a separate resource dictionary file, its scope is determined by where the resource dictionary is referenced.

Style 定义中,你需要一个 TargetType 属性和由一个或多个 Setter 元素组成的集合。In the Style definition, you need a TargetType attribute and a collection of one or more Setter elements. TargetType 属性是一个指定要应用样式的 FrameworkElement 类型的字符串。The TargetType attribute is a string that specifies a FrameworkElement type to apply the style to. TargetType 值必须指定由 Windows 运行时定义的派生的 FrameworkElement 类型或引用的程序集中提供的自定义类型。The TargetType value must specify a FrameworkElement-derived type that's defined by the Windows Runtime or a custom type that's available in a referenced assembly. 如果你试图将某个样式应用到某控件,而此控件的类型与你试图应用的样式的 TargetType 属性不匹配,则会发生异常。If you try to apply a style to a control and the control's type doesn't match the TargetType attribute of the style you're trying to apply, an exception occurs.

每个 Setter 元素都需要一个 Property 和一个 ValueEach Setter element requires a Property and a Value. 这些属性设置用于指示该设置将应用于哪个控件属性,以及为该属性设置的值。These property settings indicate what control property the setting applies to, and the value to set for that property. 你可以使用特性或属性元素语法设置 Setter.ValueYou can set the Setter.Value with either attribute or property element syntax. 下面的 XAML 显示了应用于前面显示的按钮的样式。The XAML here shows the style applied to the buttons shown previously. 在此 XAML 中,前两个 Setter 元素使用特性语法,但是最后一个 Setter(用于设置 BorderBrush 属性)使用属性元素语法。In this XAML, the first two Setter elements use attribute syntax, but the last Setter, for the BorderBrush property, uses property element syntax. 该示例不使用 x:Key 特性这一特性,因此该样式已隐式应用到按钮。The example doesn't use the x:Key attribute attribute, so the style is implicitly applied to the buttons. 隐式或显式应用样式在下一节进行介绍。Applying styles implicitly or explicitly is explained in the next section.

<Page.Resources>
    <Style TargetType="Button">
        <Setter Property="BorderThickness" Value="5" />
        <Setter Property="Foreground" Value="Black" />
        <Setter Property="BorderBrush" >
            <Setter.Value>
                <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                    <GradientStop Color="Yellow" Offset="0.0" />
                    <GradientStop Color="Red" Offset="0.25" />
                    <GradientStop Color="Blue" Offset="0.75" />
                    <GradientStop Color="LimeGreen" Offset="1.0" />
                </LinearGradientBrush>
            </Setter.Value>
        </Setter>
    </Style>
</Page.Resources>

<StackPanel Orientation="Horizontal">
    <Button Content="Button"/>
    <Button Content="Button"/>
    <Button Content="Button"/>
</StackPanel>

应用隐式或显式样式Apply an implicit or explicit style

如果你将样式定义为资源,有两种方法可将其应用到控件:If you define a style as a resource, there are two ways to apply it to your controls:

如果样式包含 x:Key 特性,则只能通过将控件的 Style 属性设置为键控样式,从而将其应用到控件。If a style contains the x:Key attribute, you can only apply it to a control by setting the Style property of the control to the keyed style. 相反,没有 x:Key 特性的样式会自动应用到其目标类型的每个控件,这些控件没有显示样式设置。In contrast, a style without an x:Key attribute is automatically applied to every control of its target type, that doesn't otherwise have an explicit style setting.

下面两个按钮演示了隐式和显示样式。Here are two buttons that demonstrate implicit and explicit styles.

隐式和显示样式按钮。

在本示例中,第一个样式具有 x:Key 特性,其目标类型为 ButtonIn this example, the first style has an x:Key attribute and its target type is Button. 第一个按钮的 Style 属性设置为此关键字,所以显示应用该样式。The first button's Style property is set to this key, so this style is applied explicitly. 第二个样式会隐式应用到第二个按钮,因为该按钮的目标类型为 Button,并且该样式没有 x:Key 特性。The second style is applied implicitly to the second button because its target type is Button and the style doesn't have an x:Key attribute.

<Page.Resources>
    <Style x:Key="PurpleStyle" TargetType="Button">
        <Setter Property="FontFamily" Value="Segoe UI"/>
        <Setter Property="FontSize" Value="14"/>
        <Setter Property="Foreground" Value="Purple"/>
    </Style>

    <Style TargetType="Button">
        <Setter Property="FontFamily" Value="Segoe UI"/>
        <Setter Property="FontSize" Value="14"/>
        <Setter Property="RenderTransform">
            <Setter.Value>
                <RotateTransform Angle="25"/>
            </Setter.Value>
        </Setter>
        <Setter Property="BorderBrush" Value="Green"/>
        <Setter Property="BorderThickness" Value="2"/>
        <Setter Property="Foreground" Value="Green"/>
    </Style>
</Page.Resources>

<Grid x:Name="LayoutRoot">
    <Button Content="Button" Style="{StaticResource PurpleStyle}"/>
    <Button Content="Button"/>
</Grid>

基于样式使用Use based-on styles

为了使样式便于维护以及优化样式的重复使用,你可以创建从其他样式继承的样式。To make styles easier to maintain and to optimize style reuse, you can create styles that inherit from other styles. 使用 BasedOn 属性可创建继承的样式。You use the BasedOn property to create inherited styles. 从其他样式继承的样式必须应用到同一类型的控件,或者从基本样式的目标类型派生出来的控件。Styles that inherit from other styles must target the same type of control or a control that derives from the type targeted by the base style. 例如,如果基本样式的目标类型为 ContentControl,则基于此样式的样式可应用到 ContentControl 或从 ContentControl 派生的类型(如 ButtonScrollViewer)。For example, if a base style targets ContentControl, styles that are based on this style can target ContentControl or types that derive from ContentControl such as Button and ScrollViewer. 如果基于样式的值没有设置,则从基本样式继承。If a value is not set in the based-on style, it's inherited from the base style. 要从基本样式更改值,基于样式会覆盖该值。To change a value from the base style, the based-on style overrides that value. 下一个示例演示了具有从同一基本样式继承的样式的 ButtonCheckBoxThe next example shows a Button and a CheckBox with styles that inherit from the same base style.

使用基于样式的样式设计按钮。

基本样式应用到 ContentControl,并设置 HeightWidth 属性。The base style targets ContentControl, and sets the Height, and Width properties. 基于此样式的样式应用到 CheckBoxButton,这些类型从 ContentControl 派生而来。The styles based on this style target CheckBox and Button, which derive from ContentControl. 基于样式为 BorderBrushForeground 属性设置不同的颜色。The based-on styles set different colors for the BorderBrush and Foreground properties. (通常不在 CheckBox 的周围加边框。(You don't typically put a border around a CheckBox. 我们在此处执行此操作,来显示样式的效果。)We do it here to show the effects of the style.)

<Page.Resources>
    <Style x:Key="BasicStyle" TargetType="ContentControl">
        <Setter Property="Width" Value="130" />
        <Setter Property="Height" Value="30" />
    </Style>

    <Style x:Key="ButtonStyle" TargetType="Button"
           BasedOn="{StaticResource BasicStyle}">
        <Setter Property="BorderBrush" Value="Orange" />
        <Setter Property="BorderThickness" Value="2" />
        <Setter Property="Foreground" Value="Red" />
    </Style>

    <Style x:Key="CheckBoxStyle" TargetType="CheckBox"
           BasedOn="{StaticResource BasicStyle}">
        <Setter Property="BorderBrush" Value="Blue" />
        <Setter Property="BorderThickness" Value="2" />
        <Setter Property="Foreground" Value="Green" />
    </Style>
</Page.Resources>

<StackPanel>
    <Button Content="Button" Style="{StaticResource ButtonStyle}" Margin="0,10"/>
    <CheckBox Content="CheckBox" Style="{StaticResource CheckBoxStyle}"/>
</StackPanel>

使用工具轻松处理样式Use tools to work with styles easily

将样式应用到控件的一种快捷方式是,在 Microsoft Visual Studio XAML 设计界面上,右键单击控件并选择“编辑样式” 或“编辑模板” (取决于右键单击的控件)。A fast way to apply styles to your controls is to right-click on a control on the Microsoft Visual Studio XAML design surface and select Edit Style or Edit Template (depending on the control you are right-clicking on). 然后,通过选择“应用资源” 来应用现有样式,或通过选择“创建空项” 来定义一个新样式。You can then apply an existing style by selecting Apply Resource or define a new style by selecting Create Empty. 如果创建空白样式,则可以使用相应的选项在该页面、App.xaml 文件或一个单独的资源字典中进行定义。If you create an empty style, you are given the option to define it in the page, in the App.xaml file, or in a separate resource dictionary.

轻型样式设置Lightweight styling

通常在应用级别或页面级别上替代系统画笔,在任意情况下,颜色替代都将影响引用该画笔的所有控件;在 XAML 中,许多控件可以引用相同的系统画笔。Overriding the system brushes is generally done at the App or Page level, and in either case the color override will affect all controls that reference that brush – and in XAML many controls can reference the same system brush.

通过样式设计的按钮

<Page.Resources>
    <ResourceDictionary>
        <ResourceDictionary.ThemeDictionaries>
            <ResourceDictionary x:Key="Light">
                 <SolidColorBrush x:Key="ButtonBackground" Color="Transparent"/>
                 <SolidColorBrush x:Key="ButtonForeground" Color="MediumSlateBlue"/>
                 <SolidColorBrush x:Key="ButtonBorderBrush" Color="MediumSlateBlue"/>
            </ResourceDictionary>
        </ResourceDictionary.ThemeDictionaries>
    </ResourceDictionary>
</Page.Resources>

对于诸如 PointerOver(鼠标悬停在按钮上)、PointerPressed(按钮已调用)或 Disabled(按钮不可交互)的状态。For states like PointerOver (mouse is hovered over the button), PointerPressed (button has been invoked), or Disabled (button is not interactable). 这些后缀将追加到原始轻型样式设置名称:ButtonBackgroundPointerOverButtonForegroundPointerPressedButtonBorderBrushDisabled 等。修改这些画笔还将确保控件的配色与应用的主题保持一致。These endings are appended onto the original Lightweight styling names: ButtonBackgroundPointerOver, ButtonForegroundPointerPressed, ButtonBorderBrushDisabled, etc. Modifying those brushes as well, will make sure that your controls are colored consistently to your app's theme.

App.Resources 级别上放置这些画笔替代将更改整个应用(而不是单个页面)内的所有按钮。Placing these brush overrides at the App.Resources level, will alter all the buttons within the entire app, instead of on a single page.

每个控件的样式设置Per-control styling

在其他情况下,需要仅以特定方式更改一个页面上的单个控件,而不更改该控件的任何其他版本:In other cases, changing a single control on one page only to look a certain way, without altering any other versions of that control, is desired:

通过样式设计的按钮

<CheckBox Content="Normal CheckBox" Margin="5"/>
<CheckBox Content="Special CheckBox" Margin="5">
    <CheckBox.Resources>
        <ResourceDictionary>
            <ResourceDictionary.ThemeDictionaries>
                <ResourceDictionary x:Key="Light">
                    <SolidColorBrush x:Key="CheckBoxForegroundUnchecked"
                        Color="Purple"/>
                    <SolidColorBrush x:Key="CheckBoxForegroundChecked"
                        Color="Purple"/>
                    <SolidColorBrush x:Key="CheckBoxCheckGlyphForegroundChecked"
                        Color="White"/>
                    <SolidColorBrush x:Key="CheckBoxCheckBackgroundStrokeChecked"  
                        Color="Purple"/>
                    <SolidColorBrush x:Key="CheckBoxCheckBackgroundFillChecked"
                        Color="Purple"/>
                </ResourceDictionary>
            </ResourceDictionary.ThemeDictionaries>
        </ResourceDictionary>
    </CheckBox.Resources>
</CheckBox>
<CheckBox Content="Normal CheckBox" Margin="5"/>

这仅影响存在该控件的页面上的一个“特殊复选框”。This would only effect that one “Special CheckBox” on the page where that control existed.

修改默认系统样式Modify the default system styles

在可以使用来自 Windows 运行时默认 XAML 资源的样式时,应使用这些样式。You should use the styles that come from the Windows Runtime default XAML resources when you can. 在必须定义自己的样式时,如果可能,请尝试以默认样式为基础(如前所述,使用基于样式,或先编辑最初默认样式的副本)。When you have to define your own styles, try to base your styles on the default ones when possible (using based-on styles as explained earlier, or start by editing a copy of the original default style).

template 属性The template property

样式 setter 可用于 ControlTemplate 属性,实际上,此样式构成了多数典型的 XAML 样式和应用的 XAML 资源。A style setter can be used for the Template property of a Control, and in fact this makes up the majority of a typical XAML style and an app's XAML resources. 此内容将在主题控件模板中更详细地讨论。This is discussed in more detail in the topic Control templates.