





















































So far, you've seen that while styles can change the look of a control, they can only go so far. No matter how many changes we make, the buttons still look like old-fashioned buttons. Surely, there must be a way to customize a control further to match our creative vision. There is a way, its called skinning.
Controls in Silverlight are extremely flexible and customizable. This flexibility stems from the fact that controls have both a VisualTree and a LogicalTree. The VisualTree deals with all the visual elements in a control, while the Logical tree deals with all the logical elements. All controls in Silverlight come with a default template, which defines what a control should look like. You can easily override this default template by redefining a control's visual tree with a custom one.
Designers can either work directly with XAML in Blend or use a design tool that supports exporting to XAML. Expression Design is one such tool. You can alsoimport artwork from Adobe Illustrator and Adobe Photoshop from within Blend.
In our scenario, let us pretend that there is a team of graphic designers. From time to time graphic designers will provide us with visual elements and, if we're lucky, snippets of XAML. In this case, the designers have sent us the XAML for a rectangle and gradient for us to base our control on:
<Rectangle Stroke="#7F646464" Height="43" Width="150"
StrokeThickness="2" RadiusX="15" RadiusY="15" VerticalAlignment="Top">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFEE9D9D" Offset="0.197"/>
<GradientStop Color="#FFFF7D7D" Offset="0.847"/>
<GradientStop Color="#FFF2DADA" Offset="0.066"/>
<GradientStop Color="#FF7E4F4F" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
After inputting the above XAML, you will be presented with this image:
We need to make this rectangle the template for our buttons.
We're going to take the XAML snippet above and skin our buttons with it. In order to achieve this we will need to do the following:
(</StackPanel>)
<Rectangle Stroke="#7F646464" Height="43" Width="150"
StrokeThickness="2" RadiusX="15" RadiusY="15"
VerticalAlignment="Top" >
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFEE9D9D" Offset="0.197"/>
<GradientStop Color="#FFFF7D7D" Offset="0.847"/>
<GradientStop Color="#FFF2DADA" Offset="0.066"/>
<GradientStop Color="#FF7E4F4F" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
The result is still not quite what we're looking for, but it's close. We need to increase the font size again; fortunately, we know how easy that is in Blend.
We just took a plain old button and turned it into something a little more in line with the graphic designers' vision but how did we do it?
When in doubt, look at the XAML
The nice thing about Silverlight is that you can always take a look at the XAML to get a better understanding of what's going on. There are many places where things can "hide" in a tool like Blend or even Visual Studio. The raw naked XAML, however, bares all.
For starters, we took a chunk of XAML and, using Blend, told Silverlight that we wanted to "take control" over how this button looks. This data was encapsulated into a Style and we told all our buttons to use our new style. When the new style was created, we lost some of our formatting data. We then inserted it back in and added a few more properties.
If you're really curious to see what's going on, let's take a closer look at the XAML that Blend just generated for us:
<Style TargetType="Button">
<Setter Property="FontSize" Value="18.667"/>
<Setter Property="Background" Value="Red"/>
<Setter Property="FontStyle" Value="Italic"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Margin" Value="5"/>
</Style>
<Style x_Key="smallerTextStyle" TargetType="Button">
<Setter Property="FontSize" Value="9"/>
</Style>
<Style x_Key="navButtonStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Rectangle RadiusY="15" RadiusX="15" Stroke="#7F646464"
StrokeThickness="2">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="#FFEE9D9D" Offset="0.197"/>
<GradientStop Color="#FFFF7D7D" Offset="0.847"/>
<GradientStop Color="#FFF2DADA" Offset="0.066"/>
<GradientStop Color="#FF7E4F4F" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<ContentPresenter HorizontalAlignment="{TemplateBinding
HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding
VerticalContentAlignment}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="FontSize" Value="24"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Height" Value="45"/>
<Setter Property="Width" Value="200"/>
</Style>
You'll immediately notice how verbose XAML can be. We've not done a great deal of work, yet we've generated a lot of XAML. This is where a tool like Blend really saves us all those keystrokes. The next thing you'll see is that we're actually setting the Template property inside of a Setter node of a Style definition. It's not until toward the end of the Style definition that we see the Rectangle which we started with. There's also a lot of code here devoted to something called the Visual State Manager.
Prior to us changing the control's template, you'll remember that when you moved your mouse over any of the buttons, they reacted by changing color. This was nice, subtle feedback for the user. Now that it's gone, we really miss it and so will our users. If you carefully study the XAML, it should come as no surprise to you that the button doesn't do anything other than just sit there: we've not defined anything for any of the states listed here. The nodes are blank. Let's do that now.