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

在 XAML 框架中,如果要自定义控件的可视结构和可视行为,请创建控件模板。控件有多个属性,如 Background、Foreground 以及FontFamily,可以设置这些属性以指定控件外观的多个方面。但是可以通过设置这些属性所做的更改有限。可以使用 ControlTemplate 类创建提供其他自定义的模板。在此处,我们介绍如何创建 ControlTemplate 以自定义 CheckBox 控件的外观。
路线图: 本主题与其他主题有何关联?请参阅:
自定义控件模板示例
在默认情况下,CheckBox 控件将其内容(字符串或 CheckBox 旁的对象)放在选择框的右侧。这是 CheckBox 的可视结构。在默认情况下,复选标记表示用户已选定 CheckBox。这是 CheckBox 的可视行为。你可以通过为 CheckBox 创建 ControlTemplate 来更改这些特性。例如,假定你想要让复选框的内容显示在选择框下方,并且你想要用 X 来表示用户已选定复选框。你可以在 CheckBox 的 ControlTemplate 中指定这些特性。
下面是分别在 Unchecked、Checked 和 Indeterminate 状态下使用默认 ControlTemplate 的 CheckBox。

要为控件使用自定义模板,请将 ControlTemplate 分配给控件的 Template 属性。下面是使用称为CheckBoxTemplate1 的 ControlTemplate 的 CheckBox。我们在下一节介绍 ControlTemplate 的 Extensible Application Markup Language (XAML)。
<CheckBox Content="CheckBox" Template="{StaticResource CheckBoxTemplate1}" IsThreeState="True" Margin="20"/>
下面是在应用模板后,CheckBox 在 Unchecked、Checked 和 Indeterminate 状态下的外观。

指定控件的可视结构。
当你创建 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 中复选状态:Checked、Unchecked 和Indeterminate。IsChecked 属性的值确定 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 介绍在 Checked、Unchecked 和 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 主题资源引用中。
WP8.1学习系列(第二十六章)——控件模板的更多相关文章
- WP8.1学习系列(第二十五章)——控件样式
XAML 框架提供许多自定义应用外观的方法.通过样式可以设置控件属性,并重复使用这些设置,以便保持多个控件具有一致的外观. 路线图: 本主题与其他主题有何关联?请参阅: 使用 C# 或 Visua ...
- WP8.1学习系列(第二十二章)——在页面之间导航
在本文中 先决条件 创建导航应用 Frame 和 Page 类 页面模板中的导航支持 在页面之间传递信息 缓存页面 摘要 后续步骤 相关主题 重要的 API Page Frame Navigation ...
- WP8.1学习系列(第二十四章)——Json解析
.net已经集成了json解析,类名叫DataContractJsonSerializer DataContractJsonSerializer 类型公开以下成员. 构造函数 名称 说明 Da ...
- WP8.1学习系列(第十六章)——交互UX之命令模式
命令模式 在本文中 命令类型 命令放置 相关主题 你可以在应用商店应用的几个曲面中放置命令和控件,包括应用画布.弹出窗口.对话框和应用栏.在正确的时间选择合适的曲面可能就是易于使用的应用和很难使用 ...
- WP8.1学习系列(第十九章)——事件和路由事件概述
我们将介绍在使用 C#.Visual Basic 或 Visual C++ 组件扩展 (C++/CX) 作为编程语言并使用 XAML 进行 UI 定义时,针对 Windows 运行时应用的事件的编程概 ...
- WP8.1学习系列(第十二章)——全景控件Panorama开发指南
2014/6/18 适用于:Windows Phone 8 和 Windows Phone Silverlight 8.1 | Windows Phone OS 7.1 全景体验是本机 Windows ...
- 【WPF学习】第二十六章 Application类——应用程序的生命周期
在WPF中,应用程序会经历简单的生命周期.在应用程序启动后,将立即创建应用程序对象,在应用程序运行时触发各种应用程序事件,你可以选择监视其中的某些事件.最后,当释放应用程序对象时,应用程序将结束. 一 ...
- 【WPF学习】第十九章 控件类
WPF窗口充满了各种元素,但这些元素中只有一部分是控件.在WPF领域,控件通常被描述为与用户交互的元素——能接收焦点并接受键盘或鼠标输入的元素.明显的例子包括文本框和按钮.然而,这个区别有时有些模糊. ...
- “全栈2019”Java多线程第二十六章:同步方法生产者与消费者线程
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
随机推荐
- EF5+MVC4系列(5) 删除的方法 1:系统推荐的先查询后remove删除的方法 2:自己new一个包含主键的类,然后 attach附加 remove删除;3:使用db.Entry 修改状态删除4:EntityState的几种状态
我们还是以订单表为例 1:系统推荐的方法,先查询出来,然后调用remove方法进行删除 我们删除id大于等于4的 static void Main(string[] args) { Delet ...
- erlang的erl文件的编码方式
在数据源头的文件第一行加上%%coding: latin-1
- C#页面前台<%%><%#%><%=%>
ASP.net前台绑定用的最多,今天小小总结一下. 1:<%#Eval("")%> 2:<%#Bind("")%> 3:<%=变量 ...
- unity3d Matrix4x4列为主序
unity3d的矩阵一直用,但是之前都是测试着用的,效果虽然正确,但是一直没搞清楚它是行矩阵还是列矩阵 今天测试了下 Matrix4x4 mat4 = Matrix4x4.Perspective(30 ...
- 边框颜色为 tintColor 的 UIButton
创建一个 UIButton 的子类,重写其方法: - (void)drawRect:(CGRect)rect { [[self layer] setCornerRadius:CORNER_RADIUS ...
- 用C++做微信公众平台开发的后台开发时,用sha1加密验证的方法
微信公众平台开发时,须要验证消息是否来自微信server,这要用到sha1加密算法.官网上给的是php的sha函数,C++中要用到以下这个函数: 一.引入头文件: #include<openss ...
- Dominoserver 安装
domino安装及语言包安装 http://wenku.baidu.com/view/f473600d581b6bd97f19ea9b.html dominoserver 安装后启动配置: http: ...
- highcharts学习1----Line charts
今天开始将之前使用的highcharts控件的经验进行总结和整理,一方面方便自己以后使用查询,同时也为正在学习的人们做一些指引,算是资源分享吧. 官网链接: http://www.highcharts ...
- sql2008修改管理员与普通用户密码
方法一: sp_password Null,'123,'sa'把sa的密码设为“123” 执行成功后有“Command(s) completed successfully.” OK! 方法二: 第一步 ...
- Owe Her
I owe her too much a wedding, i think i never pay her for it a life,