今天我们开始着手上一篇文章提到的实现用户动态按钮功能。
同样我们对上一章的代码进行修改按键特效。首先我们将原来的按键样式代码删掉,修改如下代码:
1 <Window.Resources> 2 <Style TargetType="Button"> 3 <Setter Property="Template"> 4 <Setter.Value> 5 <ControlTemplate TargetType="Button"> 6 <Border x:Name="Border" CornerRadius="20" BorderBrush="PaleGreen" BorderThickness=" 1"> 7 <Border.Background> 8 <LinearGradientBrush StartPoint=" 0,0.5" EndPoint=" 1,0.5" Opacity=" 0.5"> 9 <GradientStop Color="Green" Offset=" 0.0"/> 10 <GradientStop Color="White" Offset=" 1.0"/> 11 </LinearGradientBrush> 12 </Border.Background> 13 <ContentPresenter Margin="2" HorizontalAlignment="Center" VerticalAlignment="Center" RecognizesAccessKey="True"/> 14 </Border> 15 <ControlTemplate.Triggers> 16 <Trigger Property="IsPressed" Value="true"> 17 <Setter TargetName="Border" Property="Background"> 18 <Setter.Value> 19 <LinearGradientBrush StartPoint=" 0,0.5" EndPoint="1,0.5"> 20 <GradientStop Color="Blue" Offset="0.0"/> 21 <GradientStop Color="Red" Offset="0.5"/> 22 </LinearGradientBrush> 23 </Setter.Value> 24 </Setter> 25 </Trigger> 26 </ControlTemplate.Triggers> 27 </ControlTemplate> 28 </Setter.Value> 29 </Setter> 30 </Style> 31 </Window.Resources>
删掉后,为:
<Window.Resources>
<Style TargetType="Button">
</Style>
</Window.Resources>
在添加按键动态效果之前,我们先添加一个动态背景图案样式,及其渐变笔刷和一个按键背景渐变笔刷样本
<Window.Resources>
<!--define glass gradient stop resource-->
<GradientStopCollection x:Key="myGradientStopResource">
<GradientStop Color="WhiteSmoke" Offset="0.2"/>
<GradientStop Color="Transparent" Offset="0.4"/>
<GradientStop Color="WhiteSmoke" Offset="0.5"/>
<GradientStop Color="Transparent" Offset=" 0.75"/>
<GradientStop Color="WhiteSmoke" Offset="0.9"/>
<GradientStop Color="Transparent" Offset=" 1.0"/>
</GradientStopCollection>
<!--define gradient brush resource-->
<LinearGradientBrush x:Key="myGlassBrushResource" StartPoint="0,0" EndPoint=" 1,1" Opacity="0.75"
GradientStops="{StaticResource myGradientStopResource }"/>
<!--background brush resource-->
<LinearGradientBrush x:Key="grayBlueGradientBrush" StartPoint=" 0,0" EndPoint="1,1">
<GradientStop Color="Gray" Offset="0"/>
<GradientStop Color="Cyan" Offset="0.5"/>
<GradientStop Color="Gold" Offset="1.0"/>
</LinearGradientBrush>
<!--define button options-->
<Style TargetType="Button">
</Style>
</Window.Resources>
为按键类统一添加背景效果:
<!--define button background-->
<Setter Property="Background" Value="{StaticResource grayBlueGradientBrush}"/>
通过模板属性设计按键效果:
<!--define button template-->
<Setter Property="Template">
<Setter.Value>
<!--target type is button-->
<ControlTemplate TargetType="{x:Type Button}">
</ControlTemplate>
</Setter.Value>
</Setter>
添加外观框架:
<Grid Margin="-26,0,-56,2">
<!--outline rectangle-->
<Rectangle x:Name="outerRectangle" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" Stroke="{TemplateBinding Background}"
RadiusX="20" RadiusY="20" StrokeThickness="5" Fill="Transparent"/>
<!--inner rectangle-->
<Rectangle x:Name="innerRectangle" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" Stroke="Transparent"
StrokeThickness="20" Fill="{TemplateBinding Background}"
RadiusX="20" RadiusY="20"/>
<!--glass rectangle-->
<Rectangle x:Name="glassCube" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" StrokeThickness="2"
RadiusX="10" RadiusY="10" Opacity="0"
Fill="{StaticResource myGlassBrushResource}"
RenderTransformOrigin="0.5,0.5">
<!--rectangle stroke-->
<Rectangle.Stroke>
<LinearGradientBrush StartPoint=" 0.5,0" EndPoint="0.5,1">
<LinearGradientBrush.GradientStops>
<GradientStop Color="LightBlue" Offset="0.0"/>
<GradientStop Color="Gray" Offset="1.0"/>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Rectangle.Stroke>
<!--glass rectangle render transform-->
<Rectangle.RenderTransform>
<TransformGroup>
<!--To stretch or contact horizontally or vertially-->
<ScaleTransform/>
<!--rotate transform by angles-->
<RotateTransform/>
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle>
<!--dock panel-->
<DockPanel Name="myContentPresenterDockPanel">
<ContentPresenter x:Name="myContentPresent" Margin="20"
Content="{TemplateBinding Content}" TextBlock.Foreground="Black"/>
</DockPanel>
</Grid>
添加鼠标对按键影响动态效果
<!--control template-->
<ControlTemplate.Triggers>
<!--mouse over trigger-->
<Trigger Property="IsMouseOver" Value="True">
<!--rectangle stroke-->
<Setter Property="Rectangle.Stroke" TargetName="outerRectangle"
Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
<Setter Property="Rectangle.Opacity" Value="1" TargetName="glassCube"/>
</Trigger>
<!--Mouse focused trigger-->
<Trigger Property="IsFocused" Value="True">
<Setter Property="Rectangle.Stroke" TargetName="outerRectangle"
Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
<Setter Property="Rectangle.Opacity" Value="1" TargetName="glassCube"/>
</Trigger>
<!--Event trigger mouse enter-->
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<!--actions-->
<EventTrigger.Actions>
<!--begin story board-->
<BeginStoryboard Name="mouseEnterBeginStoryboard">
<Storyboard>
<!--animation-->
<DoubleAnimation Storyboard.TargetName="glassCube"
Storyboard.TargetProperty=
"(Rectangle.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"
By="-0.2" Duration="0:0:0.5" />
<DoubleAnimation Storyboard.TargetName="glassCube"
Storyboard.TargetProperty=
"(Rectangle.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"
By="-0.2" Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<!--event trigger mouse leave-->
<EventTrigger RoutedEvent="Mouse.MouseLeave">
<EventTrigger.Actions>
<StopStoryboard BeginStoryboardName="mouseEnterBeginStoryboard"/>
</EventTrigger.Actions>
</EventTrigger>
<!--event trigger button click-->
<EventTrigger RoutedEvent="Button.Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="glassCube"
Storyboard.TargetProperty="(Rectangle.RenderTransform).(TransformGroup.Children)[1].(RotateTransform.Angle)"
By="360" Duration="0:0:0.5"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</ControlTemplate.Triggers>
我们解析一下部分代码:
<!--mouse over trigger-->
<Trigger Property="IsMouseOver" Value="True">
<!--rectangle stroke-->
<Setter Property="Rectangle.Stroke" TargetName="outerRectangle"
Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
<Setter Property="Rectangle.Opacity" Value="1" TargetName="glassCube"/>
</Trigger>
这里操作的是鼠标移到到按键上时,外框显示高亮效果,玻璃框透明度为1(1代表不透明,值越小越透明)。同样,聚焦的时候也是对对应的外框显示相应的效果。当然我们也可以将其改为内框
<Setter Property="Rectangle.Stroke" TargetName="innerRectangle"
Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
按同样的方法,我们对鼠标移入到按键框内,为玻璃外框添加收缩效果
<!--Event trigger mouse enter-->
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<!--actions-->
<EventTrigger.Actions>
<!--begin story board-->
<BeginStoryboard Name="mouseEnterBeginStoryboard">
<Storyboard>
<!--animation-->
<DoubleAnimation Storyboard.TargetName="glassCube"
Storyboard.TargetProperty=
"(Rectangle.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"
By="-0.2" Duration="0:0:0.5" />
<DoubleAnimation Storyboard.TargetName="glassCube"
Storyboard.TargetProperty=
"(Rectangle.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"
By="-0.2" Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
其中 By="-0.2" 代表收缩程度,值越小,收缩约小。
当鼠标离开按键时,我们将按键效果设置为进入之前的状态:
<!--event trigger mouse leave-->
<EventTrigger RoutedEvent="Mouse.MouseLeave">
<EventTrigger.Actions>
<StopStoryboard BeginStoryboardName="mouseEnterBeginStoryboard"/>
</EventTrigger.Actions>
</EventTrigger>
最后我们添加当鼠标按下时,玻璃外框按中心点旋转360°:
<!--event trigger button click-->
<EventTrigger RoutedEvent="Button.Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="glassCube"
Storyboard.TargetProperty="(Rectangle.RenderTransform).(TransformGroup.Children)[1].(RotateTransform.Angle)"
By="360" Duration="0:0:0.5"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
通过Margin属性对按键重新布局一下:
<Button Grid.Row="2" Grid.Column="0" Margin="90,2,125,2" Name="submit" Click="Click_submiit" Width="Auto" >View Message</Button>
<Button Grid.Row="2" Grid.Column="1" Margin="100,2,120,2" Name="Clear" Click="Click_clean" Width="Auto">Clean Name</Button>
完整代码:

<Window x:Class="WpfControls.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" >
<Window.Resources>
<!--define glass gradient stop resource-->
<GradientStopCollection x:Key="myGradientStopResource">
<GradientStop Color="WhiteSmoke" Offset="0.2"/>
<GradientStop Color="Transparent" Offset="0.4"/>
<GradientStop Color="WhiteSmoke" Offset="0.5"/>
<GradientStop Color="Transparent" Offset=" 0.75"/>
<GradientStop Color="WhiteSmoke" Offset="0.9"/>
<GradientStop Color="Transparent" Offset=" 1.0"/>
</GradientStopCollection>
<!--define gradient brush resource-->
<LinearGradientBrush x:Key="myGlassBrushResource" StartPoint="0,0" EndPoint=" 1,1" Opacity="0.75"
GradientStops="{StaticResource myGradientStopResource }"/>
<!--background brush resource-->
<LinearGradientBrush x:Key="grayBlueGradientBrush" StartPoint=" 0,0" EndPoint="1,1">
<GradientStop Color="Gray" Offset="0"/>
<GradientStop Color="Cyan" Offset="0.5"/>
<GradientStop Color="Gold" Offset="1.0"/>
</LinearGradientBrush>
<!--define button options-->
<Style TargetType="Button">
<!--define button background-->
<Setter Property="Background" Value="{StaticResource grayBlueGradientBrush}"/>
<!--define button template-->
<Setter Property="Template">
<Setter.Value>
<!--target type is button-->
<ControlTemplate TargetType="{x:Type Button}">
<Grid Margin="-26,0,-56,2">
<!--outline rectangle-->
<Rectangle x:Name="outerRectangle" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" Stroke="{TemplateBinding Background}"
RadiusX="20" RadiusY="20" StrokeThickness="10" Fill="Transparent"/>
<!--inner rectangle-->
<Rectangle x:Name="innerRectangle" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" Stroke="Transparent"
StrokeThickness="10" Fill="{TemplateBinding Background}"
RadiusX="20" RadiusY="20"/>
<!--glass rectangle-->
<Rectangle x:Name="glassCube" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" StrokeThickness="2"
RadiusX="10" RadiusY="10" Opacity="0"
Fill="{StaticResource myGlassBrushResource}"
RenderTransformOrigin="0.5,0.5">
<!--rectangle stroke-->
<Rectangle.Stroke>
<LinearGradientBrush StartPoint=" 0.5,0" EndPoint="0.5,1">
<LinearGradientBrush.GradientStops>
<GradientStop Color="LightBlue" Offset="0.0"/>
<GradientStop Color="Gray" Offset="1.0"/>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Rectangle.Stroke>
<!--glass rectangle render transform-->
<Rectangle.RenderTransform>
<TransformGroup>
<!--To stretch or contact horizontally or vertially-->
<ScaleTransform/>
<!--rotate transform by angles-->
<RotateTransform/>
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle>
<!--dock panel-->
<DockPanel Name="myContentPresenterDockPanel">
<ContentPresenter x:Name="myContentPresent" Margin="20"
Content="{TemplateBinding Content}" TextBlock.Foreground="Black"/>
</DockPanel>
</Grid>
<!--control template-->
<ControlTemplate.Triggers>
<!--mouse over trigger-->
<Trigger Property="IsMouseOver" Value="True">
<!--rectangle stroke-->
<Setter Property="Rectangle.Stroke" TargetName="outerRectangle"
Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
<Setter Property="Rectangle.Opacity" Value="1" TargetName="glassCube"/>
</Trigger>
<!--Mouse focused trigger-->
<Trigger Property="IsFocused" Value="True">
<Setter Property="Rectangle.Stroke" TargetName="innerRectangle"
Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
<Setter Property="Rectangle.Opacity" Value="1" TargetName="glassCube"/>
</Trigger>
<!--Event trigger mouse enter-->
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<!--actions-->
<EventTrigger.Actions>
<!--begin story board-->
<BeginStoryboard Name="mouseEnterBeginStoryboard">
<Storyboard>
<!--animation-->
<DoubleAnimation Storyboard.TargetName="glassCube"
Storyboard.TargetProperty=
"(Rectangle.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"
By="-0.2" Duration="0:0:0.5" />
<DoubleAnimation Storyboard.TargetName="glassCube"
Storyboard.TargetProperty=
"(Rectangle.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"
By="-0.2" Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<!--event trigger mouse leave-->
<EventTrigger RoutedEvent="Mouse.MouseLeave">
<EventTrigger.Actions>
<StopStoryboard BeginStoryboardName="mouseEnterBeginStoryboard"/>
</EventTrigger.Actions>
</EventTrigger>
<!--event trigger button click-->
<EventTrigger RoutedEvent="Button.Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="glassCube"
Storyboard.TargetProperty=
"(Rectangle.RenderTransform).(TransformGroup.Children)[1].(RotateTransform.Angle)"
By="360" Duration="0:0:0.5"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<Grid.Background>
<LinearGradientBrush StartPoint="0,1.5" EndPoint="0.5,0.1" Opacity="0.2">
<LinearGradientBrush.GradientStops>
<GradientStop Color="Green" Offset="0.0"/>
<GradientStop Color="LightBlue" Offset="0.75"/>
<GradientStop Color="LightCoral" Offset="1.2"/>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Grid.Background>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="60"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" FontSize="14" FontWeight="Bold">Entry your First Name:</Label>
<TextBox Grid.Row="0" Grid.Column="1" Name="firstName" Margin="0,5,10,5"/>
<Label Grid.Row="1">Entry your Last Name:</Label>
<TextBox Grid.Column="1" Grid.Row="1" Name="lastName" Margin="0,5,10,5"/>
<Button Grid.Row="2" Grid.Column="0" Margin="90,2,125,2" Name="submit" Click="Click_submiit" Width="Auto" >View Message</Button>
<Button Grid.Row="2" Grid.Column="1" Margin="100,2,120,2" Name="Clear" Click="Click_clean" Width="Auto">Clean Name</Button>
</Grid>
</Window>
编译运行,就可以看到我们想要的效果。
End.
谢谢。
