Monday, 9 July 2007

XAML Gel Buttons in WPF and Silverlight

I found a nice tutorial on how to create gel buttons using Inkscape, and converted the technique to XAML.

The basic idea is that you create three rounded rectangles. The main one goes from a dark colour at the top to a bright colour at the bottom. In this case, dark green to bright green.

Then there is a transparent highlight rectangle, which goes from white at the top to transparent black at the bottom. This rectangle is marginally smaller than the main rectangle, which gives us a small border. You can make it smaller using a ScaleTransform, but I found it easier to simply modify the size and corner radius.

Finally there is a drop shadow which is a transparent black rectangle (so it appears grey on a white background). Unfortunately, because Silverlight does not support the BitmapEffect property from WPF, we cannot blur this rectangle, so the effect isn't quite as nice as it could be.

Here's the code:

<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  Width="400" Height="200" Background="White">

<!-- drop shadow - needs to be blurred for correct effect -->
<Rectangle Fill="#80000000" Width="200" Height="50" Canvas.Top="52" Canvas.Left="52" RadiusX="15" RadiusY="15">
</Rectangle>


<!-- main rect -->
<Rectangle Width="200" Height="50" Canvas.Top="50" Canvas.Left="50" RadiusX="15" RadiusY="15">
<Rectangle.Fill>
   <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
     <GradientStop Offset="0" Color="#006700"/>
     <GradientStop Offset="1" Color="#00ef00"/>
   </LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>

<!-- transparent rect -->
<Rectangle Width="198" Height="48" Canvas.Top="51" Canvas.Left="51" RadiusX="14" RadiusY="14">
<Rectangle.Fill>
   <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
     <GradientStop Offset="0" Color="#FFFFFFFF"/>
     <GradientStop Offset="1" Color="#00000000"/>
   </LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Canvas>

Here's what it looks like in Silverlight:

silverlight-gel-button

Very nice! But now look what exactly the same XAML looks like in WPF:

wpf-gel-button

Yuck! I spent a while trying to work out how come the same XAML rendered differently in Silverlight and WPF. I eventually found that if I changed the bottom gradient stop in the WPF XAML to transparent white instead of transparent black, I got the same appearance as Silverlight. In fact, it looks to me like it may be the Silverlight rendering that is at fault here rather than WPF.

Anyway, if we combine this information with the blurring of the drop shadow in WPF, we can get a nice gel button in WPF as well.

<Rectangle.BitmapEffect>
<BlurBitmapEffect Radius="3" />
</Rectangle.BitmapEffect>

Here's what it looks like:

wpf-gel-button-drop-shadow

3 comments:

Anonymous said...

Hi Mark,
thank you for reporting, I filed this bug.
-Seema

Anonymous said...

Thanks for posting about this rendering difference. I've raised this issue to the WPF 2d and Silverlight teams...

Thanks,
Rob Relyea, Program Manager, WPF Team
http://robrelyea.com

Anonymous said...

Excellent website. Good work. Very useful. I will bookmark!