Sliverlight实例之 使用 ControlTemplate 自定义按钮的外观
按钮,最终效果,如下图:
见Project21_ButtonSkin
1, 创建Sliverlight项目
说明:
generic.xaml:样式和模板就被定义在这个文件里
MyButton.cs:控件的逻辑代码
2, 将下面两行代码添加到generic.xaml文件中
xmlns:src="clr-namespace:ButtonControlLibrary;assembly=ButtonControlLibrary"
xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
3,Copy按钮的默认的ControlTemplate
(1) 在Blend for VS 中打开按钮的默认模板和样式
(2) 将(1)中的按钮“默认模板和样式”xaml代码,Copy到generic.xaml文件中
4,创建初始ControlTemplate
(1) 删除 Setter 元素直到(但不包括)<Setter Property="Template">。
(2) 删除第一个 Grid 元素,但不删除它内部的元素。
(3) 删除所有 Storyboard 元素,包括它们内部的元素。
(4) 删除名为 Background 的 Border 元素,包括它内部的元素。
(5) 删除 ContentPresenter 元素。
(6) 删除名为 DisabledVisualElement 和 FocusVisualElement 的 Rectangle 元素。
Border、ContentPresenter 和 Rectangle 元素组成默认按钮控件的结构。
(7) 在 Style 元素中,将 TargetType 属性更改为 src:MyButton。
(8) 在 ControlTemplate 元素中,将 TargetType 属性更改为 src:MyButton。
5,在generic.xaml中,编辑自己的模板和样式
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:src="clr-namespace:ButtonControlLibrary;assembly=ButtonControlLibrary" xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"> <!-- 一,创建初始 ControlTemplate 二,创建可视结构 step 1,2,3,4,5,6,7 三,根据状态定义外观 step 8,9,10,11,12 四,指定可视行为 step 13 五,引用样式 step14 --> <Style x:Key="ButtonStyle1" TargetType="src:MyButton" > <!--step7 设置该按钮的默认属性--> <Setter Property="Background" Value="Navy"/> <Setter Property="Foreground" Value="White"/> <Setter Property="FontSize" Value="14"/> <Setter Property="Width" Value="100"/> <Setter Property="Height" Value="40"/> <Setter Property="Margin" Value="10"/> <Setter Property="HorizontalContentAlignment" Value="Center"/> <Setter Property="VerticalContentAlignment" Value="Center"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="src:MyButton"> <!-- step1 一个名为 RootElement 的 Border--> <Border x:Name="RootElement"> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <!--step13 使用 VisualTransition 可以指定控件转换为特定状态所耗费的时间。GeneratedDuration 属性指定转换所需的时间 --> <vsm:VisualStateGroup.Transitions> <!--指定该按钮应经过百分之一秒才进入按下状态--> <vsm:VisualTransition To="Pressed" GeneratedDuration="0:0:0.01" /> <!--指定该按钮应经过半秒才进入鼠标悬停状态--> <vsm:VisualTransition To="MouseOver" GeneratedDuration="0:0:0.5" /> <!-- 指定该按钮应经过百分之一秒才从按下状态进入鼠标悬停状态--> <vsm:VisualTransition From="Pressed" To="MouseOver" GeneratedDuration="0:0:0.01" /> <!-- 指定当控件从鼠标悬停状态转换为正常状态时某动画产生动作--> <vsm:VisualTransition From="MouseOver" To="Normal" GeneratedDuration="0:0:1.5"> <!-- 当用户将鼠标指针从按钮上移开时,按钮的边框在 1.5 秒内先变为蓝色,然后变为黄色,最后变为黑色--> <Storyboard> <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="Color" Storyboard.TargetName="BorderBrush" FillBehavior="HoldEnd" > <ColorAnimationUsingKeyFrames.KeyFrames> <LinearColorKeyFrame Value="Blue" KeyTime="0:0:0.5" /> <LinearColorKeyFrame Value="Yellow" KeyTime="0:0:1" /> <LinearColorKeyFrame Value="Black" KeyTime="0:0:1.5" /> </ColorAnimationUsingKeyFrames.KeyFrames> </ColorAnimationUsingKeyFrames> </Storyboard> </vsm:VisualTransition> </vsm:VisualStateGroup.Transitions> <VisualState x:Name="Normal"/> <VisualState x:Name="MouseOver"> <!--step8 将鼠标指针移到按钮上方时,按钮边框会设为红色--> <Storyboard> <ColorAnimation Storyboard.TargetName="BorderBrush" Storyboard.TargetProperty="Color" To="Red" /> </Storyboard> </VisualState> <VisualState x:Name="Pressed"> <!--step9 当按钮处于按下状态时,按钮边框会设为透明--> <Storyboard > <ColorAnimation Storyboard.TargetName="BorderBrush" Storyboard.TargetProperty="Color" To="Transparent" /> </Storyboard> </VisualState> <VisualState x:Name="Disabled"> <!--step10 这使得当处于禁用状态时,DisabledRect 的 Opacity 会设为 1。这样将会在按钮的 IsEnabled 属性设置为 false 时显示 DisabledRect--> <Storyboard> <DoubleAnimation Storyboard.TargetName="DisabledRect" Storyboard.TargetProperty="Opacity" To="1" Duration="0" /> </Storyboard> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="FocusStates"> <VisualState x:Name="Focused"> <!--step11 --> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusVisual" Storyboard.TargetProperty="Visibility" Duration="0"> <DiscreteObjectKeyFrame KeyTime="0"> <DiscreteObjectKeyFrame.Value> <Visibility>Visible</Visibility> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="Unfocused"> <!--step12 --> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusVisual" Storyboard.TargetProperty="Visibility" Duration="0"> <DiscreteObjectKeyFrame KeyTime="0"> <DiscreteObjectKeyFrame.Value> <Visibility>Collapsed</Visibility> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <!--step2 按钮的背景--> <Border.Background> <SolidColorBrush x:Name="BorderBrush" Color="Black"/> </Border.Background> <!--step3 作为 RootElement 的子级的 Grid--> <Grid Background="{TemplateBinding Background}" Margin="4"> <!--step4 指示按钮是否具有焦点的 Rectangle--> <Rectangle Name="FocusVisual" Visibility="Collapsed" Margin="2" Stroke="{TemplateBinding Foreground}" StrokeThickness="1" StrokeDashArray="1.5 1.5"/> <!-- step5 一个显示按钮内容的 ContentPresenter--> <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="4,5,4,4" /> <!--step6 在禁用按钮时使按钮变灰的 Rectangle--> <Rectangle x:Name="DisabledRect" Fill="#A5FFFFFF" Opacity="0" IsHitTestVisible="false" /> </Grid> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> <!-- step14 --> <Style TargetType="src:MyButton" BasedOn="{StaticResource ButtonStyle1}"></Style> </ResourceDictionary>
6,使用自定义控件
在generic.xaml中,引用样式
<!-- step14 --> <Style TargetType="src:MyButton" BasedOn="{StaticResource ButtonStyle1}"></Style>
在页面中,添加引用
xmlns:blib="clr-namespace:ButtonControlLibrary;assembly=ButtonControlLibrary"
在页面中,创建两个Button
<StackPanel> <blib:MyButton Content="Button1" /> <blib:MyButton Content="Button2" Background="Purple" /> </StackPanel>