WP8.1学习系列(第二十六章)——控件模板

Applies to Windows and Windows Phone

在 XAML 框架中,如果要自定义控件的可视结构和可视行为,请创建控件模板。控件有多个属性,如 BackgroundForeground 以及FontFamily,可以设置这些属性以指定控件外观的多个方面。但是可以通过设置这些属性所做的更改有限。可以使用 ControlTemplate 类创建提供其他自定义的模板。在此处,我们介绍如何创建 ControlTemplate 以自定义 CheckBox 控件的外观。

路线图: 本主题与其他主题有何关联?请参阅:

自定义控件模板示例

在默认情况下,CheckBox 控件将其内容(字符串或 CheckBox 旁的对象)放在选择框的右侧。这是 CheckBox 的可视结构。在默认情况下,复选标记表示用户已选定 CheckBox。这是 CheckBox 的可视行为。你可以通过为 CheckBox 创建 ControlTemplate 来更改这些特性。例如,假定你想要让复选框的内容显示在选择框下方,并且你想要用 X 来表示用户已选定复选框。你可以在 CheckBox 的 ControlTemplate 中指定这些特性。

下面是分别在 UncheckedChecked 和 Indeterminate 状态下使用默认 ControlTemplate 的 CheckBox

默认 CheckBox 模板

要为控件使用自定义模板,请将 ControlTemplate 分配给控件的 Template 属性。下面是使用称为CheckBoxTemplate1 的 ControlTemplate 的 CheckBox。我们在下一节介绍 ControlTemplate 的 Extensible Application Markup Language (XAML)。

 
<CheckBox Content="CheckBox" Template="{StaticResource CheckBoxTemplate1}" IsThreeState="True" Margin="20"/>

下面是在应用模板后,CheckBox 在 UncheckedChecked 和 Indeterminate 状态下的外观。

自定义 CheckBox 模板

指定控件的可视结构。

当你创建 ControlTemplate 时,要结合 FrameworkElement 对象来构建一个单一的控件。ControlTemplate只能有一个 FrameworkElement 作为其根元素。该根元素通常包含其他 FrameworkElement 对象。这些对象的组合组成控件的可视结构。

下面的 XAML 为 CheckBox 创建了 ControlTemplate,指定控件的内容显示在选择框的下方。根元素为Border。该示例指定 Path 来创建 X,表示用户已选定 CheckBox,并用 Ellipse 表示不确定状态。请注意,Opacity 在 PathEllipse 上设置为 0,因此在默认情况下,两者都不会显示。

 
<ControlTemplate x:Key="CheckBoxTemplate1" TargetType="CheckBox">
    <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" 
            Background="{TemplateBinding Background}">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="25"/>
            </Grid.RowDefinitions>
            <Rectangle x:Name="NormalRectangle" 
                       Fill="{ThemeResource CheckBoxBackgroundThemeBrush}"  
                       Stroke="{ThemeResource CheckBoxBorderThemeBrush}" 
                       StrokeThickness="{ThemeResource CheckBoxBorderThemeThickness}" 
                       UseLayoutRounding="False" Height="21" Width="21"/>
            <!-- Create an X to indicate that the CheckBox is selected. -->
            <Path x:Name="CheckGlyph" 
                  Data="M103,240 L111,240 119,248 127,240 135,240 123,252 135,264 127,264 119,257 111,264 103,264 114,252 z" 
                  Fill="{ThemeResource CheckBoxForegroundThemeBrush}" FlowDirection="LeftToRight" 
                  Height="14" Width="16" Opacity="0" Stretch="Fill"/>
             <Rectangle x:Name="IndeterminateGlyph" 
                     Fill="{ThemeResource CheckBoxForegroundThemeBrush}" 
                     Height="9" Width="9" Opacity="0" UseLayoutRounding="False" />
            <ContentPresenter x:Name="ContentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" 
                              Content="{TemplateBinding Content}" Margin="{TemplateBinding Padding}" Grid.Row="1" 
                              HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
        </Grid>
    </Border>
</ControlTemplate>


指定控件的可视行为

可视行为指定控件在确定状态下的外观。CheckBox 控件具有 3 中复选状态:CheckedUnchecked 和IndeterminateIsChecked 属性的值确定 CheckBox 的状态,其状态确定方框中显示的符号。

下表列出了 IsChecked 的可能值,CheckBox 的响应状态,以及 CheckBox 的外观。

IsChecked 值 CheckBox 状态 CheckBox 外观
true Checked 包含 "X"。
false Unchecked 空白。
null Indeterminate 包含一个矩形。

使用 VisualState 对象可指定控件在确定状态下的外观。VisualState 包含可更改 ControlTemplate 中元素外观的 Storyboard。当控件切换到 VisualState.Name 属性指定的状态时,Storyboard 就会开始。当控件退出该状态时,Storyboard 就会停止。你可以将 VisualState 对象添加到 VisualStateGroup 对象。还可以将VisualStateGroup 对象添加到 VisualStateManager.VisualStateGroups 附加的属性,这些对象在ControlTemplate 的根 FrameworkElement 上设置。

以下 XAML 介绍在 CheckedUnchecked 和 Indeterminate 状态下的 VisualState 对象。该示例在 Border 上设置 VisualStateManager.VisualStateGroups 附加属性,它是 ControlTemplate 的根元素。CheckedVisualState 指定名为 CheckGlyph 的 Path(已在前面的示例中介绍)的 Opacity 为 1。IndeterminateVisualState 指定名为 IndeterminateGlyph 的 Ellipse 的 Opacity 为 1。UncheckedVisualState 没有 Storyboard,因此 CheckBox 恢复为默认外观。

 
<ControlTemplate TargetType="CheckBox" x:Key="CheckBoxTemplate1">
    <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" 
            Background="{TemplateBinding Background}">
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CheckStates">
                <VisualState x:Name="Checked">
                    <Storyboard>
                        <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" 
                                         Storyboard.TargetName="CheckGlyph"/>
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="Unchecked"/>
                <VisualState x:Name="Indeterminate">
                    <Storyboard>
                        <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" 
                                         Storyboard.TargetName="IndeterminateGlyph"/>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="25"/>
            </Grid.RowDefinitions>
            <Rectangle x:Name="NormalRectangle" 
                       Fill="{ThemeResource CheckBoxBackgroundThemeBrush}"  
                       Stroke="{ThemeResource CheckBoxBorderThemeBrush}" 
                       StrokeThickness="{ThemeResource CheckBoxBorderThemeThickness}"  
                       UseLayoutRounding="False" Height="21" Width="21"/>
            <!-- Create an X to indicate that the CheckBox is selected. -->
            <Path x:Name="CheckGlyph" 
                  Data="M103,240 L111,240 119,248 127,240 135,240 123,252 135,264 127,264 119,257 111,264 103,264 114,252 z" 
                  Fill="{ThemeResource CheckBoxForegroundThemeBrush}" FlowDirection="LeftToRight" 
                  Height="14" Width="16" Opacity="0" Stretch="Fill"/>
            <Rectangle x:Name="IndeterminateGlyph" 
                     Fill="{ThemeResource CheckBoxForegroundThemeBrush}" 
                     Height="9" Width="9" Opacity="0" UseLayoutRounding="False" />
            <ContentPresenter x:Name="ContentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" 
                              Content="{TemplateBinding Content}" Margin="{TemplateBinding Padding}" Grid.Row="1" 
                              HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
        </Grid>
    </Border>
</ControlTemplate>

为了更深入地理解 VisualState 对象的工作机制,请思考当 CheckBox 从 Unchecked 状态切换到 Checked 状态,然后切换到 Indeterminate 状态,然后又恢复为 Unchecked 状态时,会发生什么。下表介绍了这些转换。

状态转换 引发的结果 转换完成时的 CheckBox 外观
从 Unchecked到 Checked CheckedVisualState 的 Storyboard 开始,所以 CheckGlyph 的 Opacity为 1。 显示 X。
从 Checked 到Indeterminate IndeterminateVisualState 的 Storyboard 开始,所以IndeterminateGlyph 的 Opacity 为 1。 CheckedVisualState 的Storyboard 结束,所以 CheckGlyph 的 Opacity 为 0。 显示一个圆形。
Indeterminate到 Unchecked IndeterminateVisualState 的 Storyboard 结束,所以IndeterminateGlyph 的 Opacity 为 0。 不显示任何符号。

有关如何创建控件视觉状态和(特别是)如何使用 Storyboard 类和动画类型的详细信息,请参阅视觉状态的情节提要动画

使用工具轻松处理主题

将主题应用到控件的一种快捷方式是,在 Microsoft Visual Studio XAML 设计界面上,右键单击控件并选择“编辑主题”或“编辑样式”(取决于右键单击的控件)。然后,通过选择“应用资源”来应用现有主题,或通过选择“创建空项”来定义一个新主题。

控件和辅助功能

为控件创建新模板时,除了可能会更改控件的行为和视觉外观外,还可能会更改控件自行代表辅助功能框架的方式。Windows 运行时支持 Microsoft UI 自动化框架用于辅助功能。所有默认控件及其模板都支持适用于控件的用途和功能的常见 UI 自动化控件类型和模式。这些控件类型和模式由 UI 自动化客户端(如辅助技术)进行解释,这样允许控件作为较大辅助应用 UI 的一部分进行访问。

若要分离基本控件逻辑以及符合 UI 自动化的某些体系结构要求,控件类在独立类(自动化对等)中包含辅助功能支持。有时自动化对等会与控件模板有交互,因为对等预期某些命名部件存在于模板中,以便可能会使用诸如允许辅助技术调用按钮操作的功能。

创建全新的自定义控件时,有时还希望随之一起新建自动化对等。有关详细信息,请参阅自定义的自动化对等

了解有关控件默认模板的详细信息

如果你查看添加控件和内容下的各种主题,会发现一些记录了现有 Windows 运行时控件的默认控件模板的主题。例如,存在名为 AppBar 样式和模板的主题,它是添加应用栏下的子主题。

记录了 Windows 运行时控件样式和模板的主题向你显示的起始 XAML 摘录与使用之前描述的编辑主题编辑样式技术时看到的相同。每个主题都将列出视觉状态的名称、使用的主题资源,以及包含该模板的样式的完整 XAML。如果你已开始修改模板并要查看原始模板的外观,或者想要验证你的新模板是否具有所有所需的命名视觉状态,这些主题将是非常有用的指南。

控件模板中的主题资源

对于 XAML 模板中的某些属性,你可能已注意到使用 ThemeResource 标记扩展的资源引用。这是一种可使单个控件模板使用资源的技术,这些资源可能采用不同的值,具体取决于当前哪个主题处于活动状态。这对于画笔和颜色尤其重要,因为主题的主要目的是使用户选择应用于整个系统的是深色主题、浅色主题,还是高对比度主题。使用 XAML 资源系统的应用可以使用适合该主题的资源集,以便应用 UI 中的主题选择可以反映用户的整个系统的主题选择。

添加控件和内容下还特别提供了其他主题,以记录现有 Windows 运行时控件的默认控件模板。作为此内容的一部分,这些主题还列出了默认模板使用的主题资源(主要是画笔)以及它们在每个主题下的值。同样,完整的主题资源集记录在 XAML 主题资源引用中。

原文地址:https://www.cnblogs.com/bvin/p/4292877.html