Gel Button Template in Silverlight
A while ago I posted about how to get a gel button effect in Silverlight. With the advent of Silverlight 2.0 beta, it is now possible to turn this into a button template for easy reuse. What's more, it is relatively straightforward to add animations for states such as MouseOver and MouseDown.
The way to go about this is to create a style in your App.xaml
file (you can put the style in any XAML page, but putting it in App.xaml
makes it available everywhere in your application).
<LinearGradientBrush x:Key="GreenGradientBrush" StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#006700"/>
<GradientStop Offset="1" Color="#00ef00"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key="RedGradientBrush" StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#774040"/>
<GradientStop Offset="1" Color="#ef4040"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key="BlueGradientBrush" StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#404077"/>
<GradientStop Offset="1" Color="#4040ef"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key="CyanGradientBrush" StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#007777"/>
<GradientStop Offset="1" Color="#00efef"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key="YellowGradientBrush" StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#777740"/>
<GradientStop Offset="1" Color="Yellow"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key="MagentaGradientBrush" StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#770077"/>
<GradientStop Offset="1" Color="#ef00ef"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key="OrangeGradientBrush" StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="DarkOrange"/>
<GradientStop Offset="1" Color="Orange"/>
</LinearGradientBrush>
<Style TargetType="Button" x:Key="GelButton">
<Setter Property="Background" Value="{StaticResource GreenGradientBrush}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid x:Name="RootElement">
<Grid.Resources>
<Storyboard x:Key='MouseOver State'>
<DoubleAnimation Storyboard.TargetName='MainButtonScale'
Storyboard.TargetProperty='ScaleX' To='1.03'
Duration='0:0:0.05'/>
<DoubleAnimation Storyboard.TargetName='MainButtonScale'
Storyboard.TargetProperty='ScaleY' To='1.03'
Duration='0:0:0.05'/>
</Storyboard>
<Storyboard x:Key='Normal State'>
</Storyboard>
<Storyboard x:Key='Pressed State'>
<DoubleAnimation Storyboard.TargetName='MainButtonTranslate'
Storyboard.TargetProperty='X' To='1.0'
Duration='0:0:0.05'/>
<DoubleAnimation Storyboard.TargetName='MainButtonTranslate'
Storyboard.TargetProperty='Y' To='1.0'
Duration='0:0:0.05'/>
</Storyboard>
<Storyboard x:Key="Disabled State">
<DoubleAnimation Duration="0:0:0"
Storyboard.TargetName="Disabled"
Storyboard.TargetProperty="Opacity"
To="1" />
</Storyboard>
</Grid.Resources>
<!-- drop shadow - needs to be blurred for correct effect -->
<Rectangle Fill="#40000000" Margin="1,1,0,0" RadiusX="6" RadiusY="6" />
<!-- main rect -->
<Grid x:Name="mainButton"
Margin="0,0,1,1"
RenderTransformOrigin="0.5,0.5">
<Grid.RenderTransform>
<TransformGroup>
<TranslateTransform x:Name="MainButtonTranslate"
X="0.0" Y="0.0"/>
<ScaleTransform
x:Name="MainButtonScale"
ScaleX="1.0" ScaleY="1.0"
/>
</TransformGroup>
</Grid.RenderTransform>
<Rectangle x:Name="mainRect"
Fill="{TemplateBinding Background}"
RadiusX="6" RadiusY="6">
</Rectangle>
<!-- transparent rect -->
<Rectangle x:Name="glowRect" Margin="1,1,1,1" RadiusX="5" RadiusY="5">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#DFFFFFFF"/>
<GradientStop Offset="1" Color="#00FFFFFF"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<ContentPresenter HorizontalAlignment="Center"
Margin="4,0,4,0"
Content="{TemplateBinding Content}"
VerticalAlignment="Center" />
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
As you can see, there is a lot of XAML, but it is fairly straightforward once you know what it is. First I have declared a load of LinearGradientBrush
es as static resources. These give me an easy way to specify a different colour scheme for the buttons without having to create a whole new template for each one.
Then there is the actual style. We have two properties. The first sets a default background for us - green, but this can be overridden in XAML. The second provides the template. This consists of the visual elements required to draw our gel button, and a number of animations.
The template XAML itself is not really any different from that shown in my original post, but there are a few exceptions. First we are using a ContentPresenter
to show the text or image that the button will contain. Second, we are using TemplateBinding
to set properties such as Background
, Foreground
etc. And finally, since we are using Grid
s, we only need to use Margin
s to position things correctly, rather than specifying sizes.
The animations are a basic scale for mouse-over which makes the buttons larger, and a translate for pressed. Interestingly, pressing the button seems to cancel the mouse-over animation, which actually has a nice visual effect so I am OK with that. Centring the scale transform was the trickiest part. I tried for ages to get a Converter
working that would use a TemplateBinding
on Width
and Height
to divide them by two, but in the end I was helped out on the Silverlight forums with a much easier solution. Simply set the RenderTransformOrigin
on the grid to 0.5,0.5
and the scale operates in the middle.
To create one of these buttons is trivially simple. This example uses the GelButton
style and changes the Background to Blue.
<Button x:Name="test3"
Margin="2"
Style="{StaticResource GelButton}"
Background="{StaticResource BlueGradientBrush}"
Height="24" Width="100"
Content="Hello World 3" />
There are some improvements that still need to be made before my GelButton
templates are complete
- Better choice of gradient colours
- Implement disabled state
- Implement focus Rectangle
- Mouse-over effect should be made a little more subtle
- Shadow effect on the content presenter?
Here's what it looks like:
Comments
Great post! thanks
KeozDear Mark,
AnonymousI got an error at
ContentPresenter HorizontalAlignment="Center" Margin="4,0,4,0" Foreground="{TemplateBinding Foreground}" Content="{TemplateBinding Content}" VerticalAlignment="Center"
saying:
The property 'Foreground' does not exist on the type 'ContentPresenter' in the XML namespace 'http://schemas.microsoft.com/winfx/2006/xaml/presentation'. C:\sources\silverlightsdemos\button2\button2\button1\App.xaml
Alex
anonymous, this was done with Silverlight 2 beta. It needs updating to work with the final release. If I ever get round to it I'll post an update here
Mark H