Control templates, Visual State Manager, and Event Handlers in Silverlight 4

Exclusive offer: get 50% off this eBook here
Microsoft Silverlight 4 Business Application Development: Beginner’s Guide

Microsoft Silverlight 4 Business Application Development: Beginner’s Guide — Save 50%

Build enterprise-ready business applications with Microsoft Silverlight 4 with this book and eBook

$32.99    $16.50
by Frank LaVigne | April 2010 | Beginner's Guides Microsoft Web Development Web Graphics & Video

In this article by Frank LaVigne, author of Microsoft Silverlight 4 Business Application Development, we shall use control templates to enhance the look and feel of the navigation widget.

Skinning a control

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:

Microsoft Silverlight 4 Business Application Development: Beginner’s Guide

We need to make this rectangle the template for our buttons.

Time for action – Skinning a control

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:

  1. Open up the CakeNavigationButtons project in Blend.
  2. In the MainPage.XAML file, switch to XAML View, either by clicking the XAML button on the upper-right corner of the art board or choosing View|Active Document View|XAML from the menu bar.
  3. Type in the following XAML after the closing tag for the StackPanel:
  4. (</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>

  5. Switch back to Design View, either by clicking on the appropriate button on the upper right corner of the art board or choosing View|Active Document View|Design View from the menu bar.
  6. Right-click on the rectangle and click on Make Into Control.
  7. Microsoft Silverlight 4 Business Application Development: Beginner’s Guide

  8. In the dialog box, choose Button, change the Name (Key) field to navButtonStyle and click OK.
  9. Microsoft Silverlight 4 Business Application Development: Beginner’s Guide

  10. You are now in template editing mode. There are two on-screen indicators that you are in this mode: one is the Objects and Timeline tab:
  11. Microsoft Silverlight 4 Business Application Development: Beginner’s Guide

  12. And one is the MainControl.xaml at the top of the art board:
  13. Microsoft Silverlight 4 Business Application Development: Beginner’s Guide

  14. Click on the up button to exit template editing mode.
  15. Delete the button that our Rectangle was converted into.
  16. Select all the buttons in the StackPanel by clicking on the first one and then Shift+clicking on the last one.
  17. With all the buttons selected, go to the Properties tab, type Style into the search box.
  18. Using the techniques you've learned in this chapter, change the style to navButtonStyle, so that your screen now looks like this:
  19. Microsoft Silverlight 4 Business Application Development: Beginner’s Guide

    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.

  20. Click on one of the buttons and choose Object|Edit Style|Edit Current from the menu bar to get into style editing mode.
  21. Make note of all the visual indicators. In the Properties tab, change the FontSize to 18, the Cursor to Hand, the Height to 45, and the Width to 200. You should see the changes immediately. The cursor change will only be noticeable at run time.
  22. Exit the template editing mode.
  23. There is a slight problem with the last button; the font is a little too large. Click on the button and use the Properties tab to change the FontSize to 12.
  24. Run the project and your application will look something like this:
  25. Microsoft Silverlight 4 Business Application Development: Beginner’s Guide

  26. Run your mouse over the buttons. The button no longer reacts when you mouse over it, we'll fix that next.

What just happened?

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.

Microsoft Silverlight 4 Business Application Development: Beginner’s Guide Build enterprise-ready business applications with Microsoft Silverlight 4 with this book and eBook
Published: April 2010
eBook Price: $32.99
Book Price: $54.99
See more
Select your format and quantity:

States of mind

The Visual State Manager, as its name implies, helps you manage the visual states of controls. It is a simple and powerful means to provide state transitions to controls, while hiding a lot of the animation mechanisms behind them.

Time for action – learning the Visual State Manager

In this exercise, we are going to use the Visual State Manager to add visual cues to our control template. While we could type out all this XAML, let's have Blend generate all the XAML for us. In order to do this, we will need to complete the following steps:

  1. In the MainPage.XAML file of the CakeNavigationButtons project, right-click on any of the buttons that use the navButtonStyle.
  2. Click Edit Template|Edit Current from the context menu as in this screenshot:
  3. Microsoft Silverlight 4 Business Application Development: Beginner’s Guide

  4. Click on the States tab in the upper-left part of the Blend window as shown below:
  5. Microsoft Silverlight 4 Business Application Development: Beginner’s Guide

  6. Click on Normal. Note how the art board gets a red border and tells you that Normal state recording is on.
  7. Click on MouseOver and then click on Rectangle in the Objects and Timeline tab.
  8. Use the Properties tab to change the background of the rectangle by changing the colors of the gradient. You can do this by clicking each one of the "stops" along the gradient line as seen in the following screenshot:
  9. Microsoft Silverlight 4 Business Application Development: Beginner’s Guide

  10. First click on stop, then use the color picker to choose a new color. You can pick your own colors. Repeat for each of the four gradient stops.
  11. Click the up button on the Objects and Timeline tab to exit the template editing mode.
  12. Run the solution and each button changes color when you mouse over it:
  13. Microsoft Silverlight 4 Business Application Development: Beginner’s Guide

  14. Then, close the browser and go back to Blend. While that worked, it doesn't quite have that same natural feel that the default button template had.
  15. We can quickly remedy that by going back into the template editing mode and changing the Default Transition property in the States tab to 0.2s as shown in the following screenshot:
  16. Microsoft Silverlight 4 Business Application Development: Beginner’s Guide

  17. Run the solution again and notice how "natural" that feels. Experiment with different timings to see how it changes the feel of your application. You can use any time in the range of 0 to 1 second.

What just happened?

We restored the natural "feel" of our navigation button by modifying how it transitions from one state to another. Because we used the Button control as a basis, several states were already defined and we got a lot of functionality "for free."

If you take a closer look at the XAML, it is starting to get really bloated at this point. Yet, our button code is still simple and humble. It's largely remains unchanged from when we started this chapter:

<Button Content="Home" Style="{StaticResource navButtonStyle}" />
<Button Content="Gallery" Style="{StaticResource navButtonStyle}" />
<Button Content="Order" Style="{StaticResource navButtonStyle}" />
<Button Content="Locations" Style="{StaticResource navButtonStyle}" />
<Button Content="Contact Us" Style="{StaticResource navButtonStyle}"
/>
<Button Content="Franchise Opportunities" Style="{StaticResource
navButtonStyle}" FontSize="14" />

Obviously, all of the work is being done inside the Style and the Control Template. The XAML code for that is quite long winded. I will just show a snippet for brevity. Here is the definition for the MouseOver state:

 

<vsm:VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames BeginTime="00:00:00"
Duration="00:00:00.0010000" Storyboard.TargetName="rectangle"
Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[
3].(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="00:00:00" Value="#FFFFFFFF"/>
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames BeginTime="00:00:00"
Duration="00:00:00.0010000" Storyboard.TargetName="rectangle"
Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[
1].(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="00:00:00" Value="#FFB1DCF4"/>
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames BeginTime="00:00:00"
Duration="00:00:00.0010000" Storyboard.TargetName="rectangle"
Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[
0].(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="00:00:00" Value="#FFE2E2E2"/>
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames BeginTime="00:00:00"
Duration="00:00:00.0010000" Storyboard.TargetName="rectangle"
Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[
2].(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="00:00:00" Value="#FFFDFDFD"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</vsm:VisualState>

You have to admire the way the Visual State Manager hid a lot of the animation XAML mark-up from us. Don't worry if it doesn't quite make sense yet. There's a lot going on here that relates to animation, but first let's get back to slinging code.

Adding event handlers

That's right, code, good old fashioned code. We are more than halfway through this chapter and we have not written one single line of procedural code. Sure, we've created plenty of XAML, but not one single line of C# or Visual Basic.NET code. How is this possible? Sharp-eyed readers may have already noticed that our MainPage.xaml file has a code behind it named MainPage.xaml.cs (MainPage.xaml.vb, if you're using Visual Basic.NET). Curious readers may have already taken a peek at the code behind the file. Here is the complete listing of code that powers our buttons:

using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace CakeNavigationButtons
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
}
}

Could that be all there is? Let's fire up Visual Studio now and take a closer look at what's going on.

Time for action – back to coding

Let's take a peek at all the code and files automatically generated for us to see what makes a typical Silverlight project tick. Let's also wire up a few event handlers to make the navigation control interactive. In order to this, we will need to do the following:

  1. Open up the CakeNavigationButtons project in Visual Studio.
  2. Open up the MainPage.xaml.cs file.
  3. Right-click on the InitializeComponent method call and select Go to Definition from the context menu.
  4. Notice that we are now in a file called mainpage.g.cs, a file that is automatically generated.
  5. Close this file and go back to the MainPage.xaml.cs file and comment out the call to InitializeComponent.
  6. Run the solution and watch what happens, absolutely nothing.
  7. Stop the solution either in Visual Studio or closing the host browser window.
  8. Uncomment the call to InitializeComponent.
  9. Open the MainPage.xaml file and inside the Home button XAML node, type Click=""> at which point Intellisense will offer to create a new event handler for you:
  10. Microsoft Silverlight 4 Business Application Development: Beginner’s Guide

  11. Click <New Event Handler>.
  12. Your button node now has a binding to an event handler.
  13. Right-click on Click="Button_Click" and click on Navigate to Event Handler from the context menu.
  14. Inside the event handler, add the following line of code and run the solution:
  15. MessageBox.Show("Hello from Silverlight");
  16. Click on the Home button and you will see this:
  17. Microsoft Silverlight 4 Business Application Development: Beginner’s Guide

  18. Click OK and then close the host browser window.
  19. Remove the following line of code we just added that showed the Alert dialog box:
  20. MessageBox.Show("Hello from Silverlight");

  21. Replace it with this line of code:
  22. System.Windows.Browser.HtmlPage.Window.Navigate(new Uri("http://
    www.packtpub.com/"));

  23. Run the project and click on the Home button once more to be taken to the Packt Publishing home page.
Microsoft Silverlight 4 Business Application Development: Beginner’s Guide

What just happened?

This should look awfully familiar to ASP.NET developers: you have a mark-up file that wires up event handlers defined in an associated code behind file. We also wrote code that popped up an alert window in the browser. This is the same kind of popup as you would see if you had coded a call to Alert in Javascript. You may not have realized it yet, but you spoke JavaScript to the host browser. The System.Windows namespace has all sorts of ways to talk to the browser and it handles all the differences between platforms and host browsers for you. Silverlight provides an HTML Bridge which allows you to interact with the host browser, and hosting HTML document.

We also could have defined the event handler and written the code in Blend, but we hadn't used Visual Studio in a while. I was beginning to worry that it may have been feeling neglected with all the work we've been doing in Blend.

 

Microsoft Silverlight 4 Business Application Development: Beginner’s Guide

Silverlight 4 has out-of-browser functionality. Despite the name, you are actually running in a browser via some clever sleight of hand.

Summary

In this article, we covered skinning a control, Visual State Manager, and adding event handlers.


If you have read this article you may be interested to view :

Microsoft Silverlight 4 Business Application Development: Beginner’s Guide Build enterprise-ready business applications with Microsoft Silverlight 4 with this book and eBook
Published: April 2010
eBook Price: $32.99
Book Price: $54.99
See more
Select your format and quantity:

About the Author :


Frank LaVigne

Frank LaVigne has been hooked on software development since he was 12, when he got his own Commodore 64 computer. Since then, he's worked as developer for fi nancial fi rms on Wall Street and also in Europe. He has worked on various Tablet PC soluti ons and on building advanced user experiences in Silverlight and WPF. He lives in the suburbs of Washington, DC. He founded the CapArea.NET User Group Silverlight Special Interest Group and has been recognized by Microsoft as a Tablet PC MVP. He blogs regularly at www.FranksWorld.com.

 

Books From Packt


Microsoft Silverlight 4 Data and Services Cookbook
Microsoft Silverlight 4 Data and Services Cookbook

Microsoft Dynamics AX 2009 Programming: Getting Started
Microsoft Dynamics AX 2009 Programming: Getting Started

Microsoft Dynamics AX 2009 Development Cookbook
Microsoft Dynamics AX 2009 Development Cookbook

SketchUp 7.1 for Architectural Visualization: Beginner's Guide
SketchUp 7.1 for Architectural Visualization: Beginner's Guide

Firebug 1.5: Editing, Debugging, and Monitoring Web Pages
Firebug 1.5: Editing, Debugging, and Monitoring Web Pages

Magento 1.3: PHP Developer's Guide
Magento 1.3: PHP Developer's Guide

3D Game Development with Microsoft Silverlight 3: Beginner's Guide
3D Game Development with Microsoft Silverlight 3: Beginner's Guide

CMS Made Simple 1.6: Beginner's Guide
CMS Made Simple 1.6: Beginner's Guide


Your rating: None Average: 1 (1 vote)
MS and it's Extraneous Code by
All of that noise to create states? Can't you just create your container element and then import a stylesheet? Having the presentation layer and application layer together is very poor coding practice. I guess that's why Silverlight won't catch on until MS decides to get serious and separate the two layers. Developers are not Designers...and vice versa. I'm using this as an example to stress we use FLEX / JSP instead of any of Microsoft's so-called "solutions".

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
8
p
Q
A
v
h
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software