Sunday, March 04, 2007

It's all in the Blend

Recently I've been experimenting with the new software tool Expression Blend. For those of you who do not know, Expression Blend is Microsoft's design tool for XAML and WPF applications and is available as I write in Beta 2 form. It provides a visual design workspace where you can lay out all the elements that make up a UI, and adjust their properties as required.

I have been making extensive use of it to style all the elements in my ribbon UI framework that I am currently developing. For someone who has previously edited the XAML directly it provides a much quicker environment for laying out the UI, with instant feedback on all changes. It also simplifies the introduction of triggers (changes on IsMouseOver, IsPressed, etc.) and animation. As an example, shown below is the application menu button for the ribbon UI. Of course since this is WPF this is all vector based, and smoothly scales up (NB: This screen grab is from an actual live UI - rollover animations, opens a menu when clicked, etc...).


In its current incarnation (beta 2) there are some issues I have had. First of all I have been unable currently to get the whole of my ribbon UI in the designer. To be fair, I haven't really tried fixing this, and it is a large composition of custom controls in a WPF rendered chrome window. It also takes a bit of learning to get used to the way it places elements by default. Of course I never read the help when I started using it which could of helped, and once you understand the basic ideas it is very easy to build up the control structure desired.

My favorite features apart from the ease at which the UI can be styled... One item I'll definitely add here is the gradient eyedropper tool. This is similar to the standard eyedropper, which can pick up individual pixel colours from the screen. However, when the gradient eyedropper tool is dragged across a region of the screen it will automatically pick up entire gradient fills. Great for designing smooth user interfaces. Also I like the simplicity by which you can apply property changes and animation upon events.

Let me know below if anybody else has any experiences of Expression Blend...



Update: After a request for the XAML code I have attached the basic code below (copy and paste into XamlPad to see it). The actual Expression Blend generated XAML is significantly more complex (and much less readable!), and includes all the roll-over behaviour etc.. This is the main reason I chose a designer over hand crafting the XAML. Hopefully the attached code will give you an idea how to approach such designs.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<Page.Resources>
<Style TargetType="{x:Type Button}" x:Key="RibbonApplicationMenuButton">
<Setter Property="Width" Value="37"/>
<Setter Property="Height" Value="37"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>

<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Border BorderThickness="0,0,0,0" CornerRadius="100000,100000,100000,100000" Opacity="1" Margin="0,0,-1,-1" x:Name="ShadowBorder" Background="#39000000"/>
<Border x:Name="OuterBorder" BorderBrush="#FF6E7D95" BorderThickness="1,1,1,1" CornerRadius="100000,100000,100000,100000">
<Border ClipToBounds="False" x:Name="InnerBorder" Width="Auto" Height="Auto" BorderBrush="#FFDDE2EC" BorderThickness="1,1,1,1" CornerRadius="10000,10000,10000,10000">
<Border.Background>
<LinearGradientBrush EndPoint="0.505,0.489" StartPoint="0.512,-0.004">
<GradientStop Color="#FFF3F5F8" Offset="0"/>
<GradientStop Color="#FFC0CADB" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
<Grid Width="Auto" Height="Auto">
<Path RenderTransformOrigin="0.499999990968993,0.0833333333333333" Stretch="Fill" Margin="0,15,0,0" x:Name="path" Width="Auto" Data="F1 M16.5,15.5 C22.163836,15.5 27.559435,15.738094 32.466614,16.168823 L32.5,16.5 C32.5,25.336555 25.336555,32.5 16.5,32.5 7.663444,32.5 0.5,25.336555 0.5000006,16.5 L0.53338605,16.168823 C5.4405661,15.738094 10.836165,15.5 16.5,15.5 z">
<Path.Fill>
<RadialGradientBrush MappingMode="RelativeToBoundingBox" GradientOrigin="0.5,0.5">
<RadialGradientBrush.RelativeTransform>
<TransformGroup>
<ScaleTransform CenterX="0.5" CenterY="0.5" ScaleX="1.077" ScaleY="1.748"/>
<SkewTransform AngleX="0" AngleY="0" CenterX="0.5" CenterY="0.5"/>
<RotateTransform Angle="0" CenterX="0.5" CenterY="0.5"/>
<TranslateTransform X="-0.002" Y="-0.025"/>
</TransformGroup>
</RadialGradientBrush.RelativeTransform>
<GradientStop Color="#FFFFFFFF" Offset="0.375"/>
<GradientStop Color="#FF93A5C2" Offset="1"/>
<GradientStop Color="#FFF2F4F7" Offset="0.529"/>
</RadialGradientBrush>
</Path.Fill>
</Path>
<ContentPresenter HorizontalAlignment="Center" Margin="0,0,0,0" VerticalAlignment="Center" Width="Auto" Height="Auto"/>
</Grid>
</Border>
</Border>
</Grid>

</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>

<Button Style="{StaticResource RibbonApplicationMenuButton}"/>
</Page>