XAML Button控件可以包含任何内容,如简单的文本,还可以给按钮添加Canvas元素,Canvas元素可以包含形状,也可以给按钮添加Grid或视频。然而,按钮还可以完成更多的操作。使用基于模版的XAML控件,控件的外观及其功能在应用中是完全分离的。虽然按钮幽默人的外观,但可以用模版完全定制其外观。
如下表所示,Windows应用程序提供了几个模版类型,它们派生自基类FrameworkTemplate。
1. 控件模版(ControlTemplate)
本章前面介绍了如何给控件的属性定义样式。如果设置控件的简单属性得不到需要的外观,就可以修改Template属性。使用Template属性可以定制控件的整体外观。下面的例子说明了定制按钮的过程,后面逐步地说明了列表框的定制,以便显示出改变的中间结果。
Button类型的定制在一个单独的资源字典文件ControlTemplates.xaml中进行。这里定义了键名为RoundedGelButton的样式。RoundedGelButton样式设置Background、Height、Foreground、Margin和Template属性。Template属性是这个样式中最有趣的部分,它指定一个仅包含一行一列的网格。
在这个单元格中,有一个名为GelBackground的椭圆。这个椭圆给笔触(Stroke)设置了一个线性渐变画笔。包围矩形的笔触非常的细,因为把StrokeThickness设置为0.5。
因为第二个椭圆GelShine比较小,其尺寸由Margin属性定义,所以在第一个椭圆内部是可见的。因为其笔触是透明的,所以该椭圆没有边框。这个椭圆使用一个线性渐变填充画笔(Fill),从部分透明的浅色变为完全透明,这使椭圆具有"亦真亦幻"的效果:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ResourcesLibUWP">
<Style x:Key="RoundedGelButton" TargetType="Button">
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="100"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse x:Name="GelBackground" StrokeThickness="0.5" Fill="Black">
<Ellipse.Stroke>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#ff7e7e7e"/>
<GradientStop Offset="1" Color="Black"/>
</LinearGradientBrush>
</Ellipse.Stroke>
</Ellipse>
<Ellipse Margin="15,5,15,50">
<Ellipse.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#aaffffff"/>
<GradientStop Offset="1" Color="Transparent"/>
</LinearGradientBrush>
</Ellipse.Fill>
</Ellipse>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
从App.xaml文件中,引用资源字典,如下所示:
<ResourceDictionary Source="ResourcesLibUWP/ControlTemplates.xaml"/>
现在可以把Button控件关联到样式上,按钮的新外观如下图所示。
<Button Content="Click Me!" Style="{StaticResource RoundedGelButton}"/>
按钮现在的外观完全不同,但按钮的内容未在上图中显示出来。必须扩展前面创建的模版,以把按钮的内容显示在新外观上。为此需要添加一个ContentPresenter。ContentPresenter是控件的占位符,并定义了放置这些内容的位置。这里把内容放在网格的第一行上,即Ellipse元素所在的位置。ContentPresenter的Content属性定义了内容的外观。把内容设置为TemplateBinding标记扩展表达式。TemplateBinding绑定父模版,这里是Button元素。{TemplateBinding Content}指定,Button控件的Content属性值应作为内容放在占位符内。下图显示了带内容的按钮:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse x:Name="GelBackground" StrokeThickness="0.5" Fill="Black">
<Ellipse.Stroke>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="1" Color="#ff7e7e7e"/>
<GradientStop Offset="0" Color="Black"/>
</LinearGradientBrush>
</Ellipse.Stroke>
</Ellipse>
<Ellipse Margin="15,5,15,50">
<Ellipse.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#aaffffff"/>
<GradientStop Offset="1" Color="Transparent"/>
</LinearGradientBrush>
</Ellipse.Fill>
</Ellipse>
<ContentPresenter x:Name="GelButtonContent" VerticalAlignment="Center" HorizontalAlignment="Center"
ContentTemplate="{TemplateBinding Content}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
注意:
TemplateBinding允许与模版交流控件定义的值。这不仅可应用于内容&#x