Visual State Manager A-Z

Mini-tutorial

This is the first of a multipart series on the Visual State Manager which will cover

  • Styles
  • Resources
  • Templates
  • Custom Controls
  • Customizing data validation

Let’s start with the form that is used in my Getting Started With Silverlight video: Adding Controls To An Application.  That video uses the design surface in Visual Studio 2010, and a subsequent video creates the grid in Xaml. To round things out I’ll create this version in Expression Blend.

I’ll begin by opening Blend and creating a new project. I’ll click  in the grid margins to create 5 rows and 2 columns.  Next, I’ll drag a TextBlock into the first row and set it properties using the properties window as shown,

TextBlockProperties

The key properties are the grid’s row and column and the horizontal and vertical alignment, as well as the font and the text itself.

For this and all images, I have cropped to the most important parts.

Also note that clicking on an image will display it in full size.

While we are here, please note that I added two yellow arrows that point to the white boxes next to some of the properties. The white box indicates that you have set that property. Clicking on the box opens the context-sensitive Advanced Options dialog box, the two most important options are Reset which reverts to the default value (and turns the  the white box gray) and data binding…. a critical topic to which we’ll return in other posts.

This layout for the text block will work well for the other three text blocks so (for now) I’ll copy and paste them into place.

Experienced developers break out in hives when they find themselves copying and pasting code like this.  Surly there is a way to factor out the common properties!?  Yup, there sure is and we’ll get to that below….

An easy way to copy the TextBlocks is to click on one, hit ctrl-C/ctrl-V and then drag the pasted copy to the row you want. Next, turn to the properties window to fix the text, name and, if needed, the margins. Note also that once they are in place, you can multi-select all the TextBlock controls and then set their common properties (e.g., the margins) all together.

Adding The Other Controls

Form in BlendAdd the remaining controls as shown in the third figure, remembering to set the prompts to flush right/bottom and the corresponding controls to flush left/bottom, all with a margin of 5.  The radio buttons and the checkboxes are put into a stack panel whose orientation is horizontal (and fully protected under the state constitution in Massachusetts).

For now, go ahead and hardwire a few ListBoxItems to reflect possible skills.

That brings us up to the state of things as of the Controls video.  Before we go ahead and wire up the button and bind to a data object, let’s take a look at some of the styling issues.

Styles

It gives me the willies to duplicate the shared styling information for each of the prompts, so let’s factor that out right away.  Return to Expression Blend and click on the first prompt (Full Name). Then select the menu option Object –> Edit Style –> Create Empty.  Name the new style Prompt and click on the New button to create a new resource file; name that file Styles.

This puts you into the editor for the style itself.  You can set the properties you want to associate with the style (e.g., horizontal and vertical alignment) an save the style; it will be saved to a file named styles.xaml which you can examine by clicking on the resources tag and then the file.

Blend will wire up that resource file into App.xaml as an external resource dictionary.   You can see this by opening the project in Visual Studio and then opening App.xaml:

[Note, I’m now using the updated version of Syntax Highlighter. You can double click anywhere in the code to copy to the clipboard. For more details, please see alexgorbatchev’s blog post ]

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Styles.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

The style itself can be seen by opening Styles.xaml:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style x:Key="Prompt" TargetType="TextBlock">
        <Setter Property="Margin" Value="5"/>
        <Setter Property="HorizontalAlignment" Value="Right"/>
        <Setter Property="VerticalAlignment" Value="Bottom"/>
        <Setter Property="Width" Value="Auto"/>
        <Setter Property="Height" Value="Auto"/>
        <Setter Property="FontFamily" Value="Georgia"/>
        <Setter Property="FontSize" Value="14"/>
        <Setter Property="FontWeight" Value="Bold"/>
    </Style>
</ResourceDictionary>

Applying the Style

To apply this style to all the prompts you’ll want first to remove these properties from the TextBlock elements.  You can do this by clicking the Advanced Properties box (the tiny white box next to the properties you set for each control) or by opening the file MainPage.xaml in the Visual Studio  Xaml editor and directly deleting the relevant attributes.

Tip: I find it very helpful to set up Visual Studio so that each property is on its own line, as shown in the code snippet below. To do this, click on Tools –> Options… and then in the options dialog box click on Text Editor –> Xaml –> Formatting –> Spacing and select Position Each Attribute On A Separate Line.

Once you have “clean” TextBlocks, you can return to Blend and click on the Resources tab. Click on the turn down next to Styles.xaml and then drag and drop the set style Prompts style onto one of the TextBlocks.

A dialog opens asking if you want to create a new TextBlock with that style, or just apply the style to the TextBlock you dropped it on.  Clickiing on the latter choice applies the Prompt style to the TextBlock.

Examining the Xaml reveals that the TextBlock’s style property has been set to the value stored in the static resource Prompt. That static resource is, again, in the Styles.xaml file.

<TextBlock
    x:Name="NamePrompt"
    Text="Full Name"
    Grid.Row="0"
    Grid.Column="0"
    Style="{StaticResource Prompt}" />

Go ahead and drag that style onto all the prompts.

Based On Styles

I’d like a style for the data entry controls as well. I could write,

<Style
    x:Key="DataEntry"
    TargetType="Control">
    <Setter
        Property="Margin"
        Value="5" />
    <Setter
        Property="HorizontalAlignment"
        Value="Left" />
    <Setter
        Property="VerticalAlignment"
        Value="Bottom" />
    <Setter
        Property="FontFamily"
        Value="Georgia" />
    <Setter
        Property="FontSize"
        Value="14" />
    <Setter
        Property="FontWeight"
        Value="Bold" />

The problem is that this is virtually a subset (and thus duplicative of) the Style for Prompts.  Clearly we’d like to factor the common pieces out.  We can do this by using the BasedOn property. We’ll create a base style for all Framework Elements, and then either add or override aspects of it in the styles we base on that style:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Style
        x:Key="FWEStyle"
        TargetType="FrameworkElement">
        <Setter
            Property="Margin"
            Value="5" />
        <Setter
            Property="HorizontalAlignment"
            Value="Right" />
        <Setter
            Property="VerticalAlignment"
            Value="Bottom" />
    </Style>

    <Style
        x:Key="Prompt"
        BasedOn="{StaticResource FWEStyle}"
        TargetType="TextBlock">
        <Setter
            Property="Width"
            Value="Auto" />
        <Setter
            Property="Height"
            Value="Auto" />
        <Setter
            Property="FontFamily"
            Value="Georgia" />
        <Setter
            Property="FontSize"
            Value="14" />
        <Setter
            Property="FontWeight"
            Value="Bold" />
        <Setter
            Property="TextWrapping"
            Value="Wrap" />
    </Style>

    <Style
        x:Key="DataEntry"
        TargetType="FrameworkElement"
        BasedOn="{StaticResource FWEStyle}">
        <Setter
            Property="HorizontalAlignment"
            Value="Left" />
    </Style>
</ResourceDictionary>

Next Steps

I will leave it, as they say, as an exercise for the reader to fill in the remaining styles and to apply those styles to the input controls.

In the next in this series, we’ll go beyond styles and examine using templates to modify the visual state of existing controls.

Share

About Jesse Liberty

Jesse Liberty is a Master Consultant for Falafel Software, and has three decades of experience writing and delivering software projects. He is the author of 2 dozen books and multiple Pluralsight courses, and has been a Technical Evangelist for Telerik and for Microsoft, a Distinguished Software Engineer for AT&T, a VP for Information Services for Citibank and a Software Architect for PBS.
This entry was posted in Blend, Mini-Tutorial, Tools and Utilities, z Silverlight Archives and tagged , . Bookmark the permalink.

4 Responses to Visual State Manager A-Z

  1. Great post Jesse! I’m going to try these steps in the future. Thank you for the method!

  2. ahole ahole says:

    ROFL Articel is about Visual State Manager A-Z
    HEY DUMBASS THERE IS NOT ONE REFERENCE TO A VISUAL STATE OBJECT IN ALL THE CODE
    ROFL

  3. Michaud says:

    I’m sorry but i wanted to mention more of the visualstatemanager on this page: http://www.bnomad.com/2010/08/silverlight-visual-state-manager.html

  4. Pingback: Styles (followup) | Jesse Liberty

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>