控件可以包含一幅图像、一段视频、一个动画,甚至一个文本框。此外还有风格、模板以及触发器等,这些功能进一步加强了控件的扩展能力。开发人员还可以修改已经存在的控件的外观,以增强它的可视化功能,而且还可以保留用户已经熟悉的控件预期行为,还可以根据特定数据输入和检查的需要,为应用程序定制自定义控件。提供的用于扩展和创建控件的基础类,为设计控件的可视化外观提供了巨大的灵活性。
一个新的控件需要先选择一个基类。可以基于许多基类来创建自定义控件,包括ControlUserControl等,当创建一个新控件时,可根据自定义控件的定制和灵活性来选择所要继承的基类,可能还需要考虑以下问题:
1)自定义控件是否由已存在的控件组成?
2)自定义控件需要定制哪些可视化外观?
3)自定义控件需要提供什么行为或功能?
作用UserControl作为基类是创建一个新控件最简单的方法,自定义控件由一引起标准控件组合在一起,来完成一个特定的用户接口功能,自定义控件可以为单个元素应用样式,并使其处理一些特定的事件,或者为控件引发特定的自定义事件。
模板的方式与样式非常类似,也可作为资源,并通过Setter来定义模板的内容。要定义模板,需要设置SetterPropertyTemplate,并使用<Setter.Value>来定义ControlTemplate来指定模板的目标类型。
模板还能保持控件的众多功能,并且可直接定义鼠标指针移入、移出以及单击的统一的变化效果。每个模板必须有一个根元素,为了方便容纳多个UI元素,根据元素通常是Panel、Grid等

范例象棋棋子按钮

   项目利用模板生成统一外观的立体棋子按扭。当鼠标单击时,外观都会有变化,如移到上面时增加阴影,单击棋子会改变效果,如图7-1
7-1
1)打开Microsoft Expression Blend,新建项目中,选择“Silverlight Application”。
2)设置二个圆形,其中一个具有渐变效果作为棋的外形,另一个带来阴影立体效果,加上“车”字,模板的外观如图7-2
7-2
 
3)将它们分成一组。选中二圆和字块后右健菜单中分成一个Grid组,如图图7-3
                      7-3
对应的主要XAML如下:
<Grid x:Name="LayoutRoot" Background="White" Margin="56,0,0,37">
           <Grid Margin="126,96,0,0" HorizontalAlignment="Left" Width="108" Height="108" VerticalAlignment="Top">
                  <Ellipse Stroke="Black" Margin="4,6,4,2" StrokeThickness="0" Height="100" Width="100" Fill="#FFA7A1A1"/>
                  <Ellipse Stroke="Black" StrokeThickness="0" Width="100" Height="100" VerticalAlignment="Top" Margin="2,0,6,0">
                         <Ellipse.Fill>
           <LinearGradientBrush EndPoint="0.795,0.998" StartPoint="0.227,-0.092">
                                       <GradientStop Color="#FF2CC017" Offset="0.032"/>
                                       <GradientStop Color="#FFC6E2C3" Offset="1"/>
                                </LinearGradientBrush>
                         </Ellipse.Fill>
                  </Ellipse>
           <TextBlock Margin="22,14,28,14" Text="" TextWrapping="Wrap" FontSize="66.667" FontWeight="Bold" Foreground="#FF17181C" FontFamily="Arial"/>
           </Grid>
    </Grid>
</UserControl>
4)将所绘制图案转换成模板。选择上面的Grid容器,即变成绘制图案的最外层对象,然后从“工具”菜单中选择“生成按扭”命令,见图7-4
7-4
 
5)出现“构成控件”对话框,选择Button,位置定义在资源字典中,可新建一个字典文件中,见图图7-5
                                             7-5
生成了一个字典文件,代码如下:
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style x:Key="ButtonStyle1" TargetType="Button">
           <Setter Property="Template">
                  <Setter.Value>
                         <ControlTemplate TargetType="Button">
                                <Grid>
                                       <VisualStateManager.VisualStateGroups>
                                              <VisualStateGroup x:Name="FocusStates">
                                                     <VisualState x:Name="Focused"/>
                                                     <VisualState x:Name="Unfocused"/>
                                              </VisualStateGroup>
                                              <VisualStateGroup x:Name="CommonStates">
                                                     <VisualState x:Name="Normal"/>
                                                     <VisualState x:Name="MouseOver"/>
                                                     <VisualState x:Name="Pressed"/>
                                                     <VisualState x:Name="Disabled"/>
                                              </VisualStateGroup>
                                       </VisualStateManager.VisualStateGroups>
                                       <Ellipse Stroke="Black" Margin="4,6,4,2" StrokeThickness="0" Height="100" Width="100" Fill="#FFA7A1A1"/>
                                       <Ellipse Stroke="Black" StrokeThickness="0" Width="100" Height="100" VerticalAlignment="Top" Margin="2,0,6,0">
                                              <Ellipse.Fill>
    <LinearGradientBrush EndPoint="0.795,0.998" StartPoint="0.227,-0.092">
                         <GradientStop Color="#FF2CC017" Offset="0.032"/>
                                <GradientStop Color="#FFC6E2C3" Offset="1"/>
                                                     </LinearGradientBrush>
                                              </Ellipse.Fill>
                                       </Ellipse>
                                       <ContentPresenter Margin="22,14,28,14"/>
                                </Grid>
                         </ControlTemplate>
                  </Setter.Value>
           </Setter>
           <Setter Property="FontFamily" Value="Arial"/>
           <Setter Property="FontWeight" Value="Bold"/>
           <Setter Property="FontSize" Value="66.667"/>
           <Setter Property="Foreground" Value="#FF17181C"/>
    </Style>
</ResourceDictionary>
 
6)现已创建了一个模板,而且也创建了一个棋子按钮,并已经将模板应用于此棋子按钮了,打开MainPage.xaml文件,可见XAML文件内容如下:
    <Grid x:Name="LayoutRoot" Background="White" Margin="56,0,0,37">
           <Button Height="108" HorizontalAlignment="Left" Margin="126,96,0,0" Style="{StaticResource ButtonStyle1}" VerticalAlignment="Top" Width="108" Content=""/>
    </Grid>
</UserControl>
7)继续编辑模板,使其具备鼠标单击的外观变换效果,双击字典文件,进入到模板编辑状态,也可从所创建的棋子控件,从级联菜单中按照顺序选择“编辑控件”、“编辑模板“、“编辑当前模板“进入,如图7-6
7-6
 
8)定义鼠标单击的外观变换效果,在左侧“状态”面板的CommonStates区域中选择Pressed状态,接着选择Ellipse的标志(棋子最外层),如图图7-7
7-7
9)使用渐变工具,修改渐变的方向,转动约180度。颜色变为从淡到深的渐变,与原来的相反,如图7-8
 
            
如图7-8
10)继续编辑模板,选择MouseOver状态,背景色设为绿色到红色的渐变,
11)模板已修改完成,保存,可安F5运行试看点击的效果。打开对应资源文件,可看到对应的XAML代码:
<VisualState x:Name="MouseOver">
    <Storyboard>
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="ellipse" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)">
                  <EasingColorKeyFrame KeyTime="00:00:00" Value="#FFE85C26"/>
    </ColorAnimationUsingKeyFrames>
           </Storyboard>
    </VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
           <PointAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="ellipse" Storyboard.TargetProperty="(Shape.Fill).(LinearGradientBrush.StartPoint)">
                  <EasingPointKeyFrame KeyTime="00:00:00" Value="0.88,0.944"/>
    </PointAnimationUsingKeyFrames>
                         <PointAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="ellipse" Storyboard.TargetProperty="(Shape.Fill).(LinearGradientBrush.EndPoint)">
           <EasingPointKeyFrame KeyTime="00:00:00" Value="0.142,-0.038"/>
    </PointAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
12)在设计画面中的MainPage.xaml中,拖放方式创建更多的Button控件,如图7-10
                          7-10
      
12)要将模板应用于Button控件,单击画面右上角的“资源”选项卡,然后找到资源文件中的模板,将模板拖放至应用的Button控件上,并且选择Style选项。这样一个个方形按钮变成了统一样式的棋子,并调整修改文字、大小等,如图7-11
7-11
13F5运行,鼠标移移到“马”上,并点击“马”后可看到会有明显的变化效果。