Structuring XAML in Blend

Working in Expression Blend, you won’t have to concern yourself with the XAML code that Blend generates. It will work. Guaranteed. Only when you start coding or changing the XAML markup by hand, you may create invalid XAML that no design view is able to render any more. To be absolutely sure that everything works as expected, Blend generates too much XAML. Attributes appear inline in the tag, properties with default values are left behind and x:null values are generated when you first enter and then clear a value. Some attributes get four values with more than 10 digits behind the decimal point each. In Silverlight the XAML for animations appear by default at the top of the XAML code of the User Control in which these are used. Also, large quantities of XAML from vector illustrations in a user interface, like logo’s, usually remain present in the XAML of a page. When you create a transformation Blend may generate markup for all possible transformations, even when you will never use them. When you generate user interface code through Blend, you ought to neglect all this. It shouldn’t even bother you. Except that under the design surface a single XAML file is generated that may be hundreds and even thousands of lines long…

An enormous XAML file is not an ideal working environment. When a web designer offers a developer a design in the form of a bitmap to implement in HTML and CSS, he risks interpretation of the design by the one who creates the code. But at least that code is minimal, optimal and fit to be worked on by other people. The code that Blend generates is optimized to be working no matter what. Markup used for lay-out and content is mixed up, making the structure of the file hard to discover. Yet, in XAML there are more than enough opportunities to structure your code. And this even can be done through the user interface of Blend. Caveats are that options for Styles and Resources are hidden and that a correct way of going about is not immediately clear. Fortunately structuring XAML in Blend is not difficult…

Use Styles

A Style is a collection of properties with a name. By giving a certain element a Style attribute with that name, all properties in the Style are applied to the element at once. Styles do not exclusively have to be visual properties. Usually they are applied more than once in an interface. You create a Style for elements with mostly similar properties that occurs repeatedly. Creating a Style in advance of using it has its advantages. 

 
In Blend you create a Style for a selected object by selecting the Edit Style option from the Object Menu. In the sub menu you can choose between:
 
  • Edit Style – to edit a Style when the selected object already has one. When you are creating a new Style this option is disabled.
  • Edit a Copy – to edit a copy of the default Style of an object. This will expand the Visual Tree of the object, which includes the ControlTemplate of the object. This may lead to an enormous amount of XAML. Especially with elements that are constructed using other elements that each have their own ControlTemplate, like Sliders and ScrollBars. 
  • Create Empty – this will create a minimal Style element
 
Only when you really need to customize a ControlTemplate to change the layout or the looks of a control, you choose for Edit a Copy… For a new Style you select Create Empty.
 
 
The dialog that appears gives you two possibilities. First you can enter a name for the Style. A meaningful, descriptive name is important to know instantly what a Style is about. The default names are not that helpful, but at least they are always unique. You may consider including the type of the control or its location on the screen in the name. Secondly you determine the scope of the Style. When you include the Style in de current control or UserControl, usually a Page control, you can retrieve and apply that Style only inside that control. When you create it at the Application level the Style will appear outside the current page in App.xaml. Now you can use this style in other UserControls as well.
 
 
One of the invisible functions of Blend is the Style Recording Mode. Notice the painters’ palette icon in the Breadcrumb Bar at the top of the screen after creating a Style. This Mode is comparable with Animation Recording Mode in the sense that everything you change in the Properties Panel is recorded in the new Style. This way you determine the basic design of certain repeating elements with a few clicks of the mouse. Hit the button to the left of the painters’ palette icon in the Breadcrumbs Bar to leave Style Recording Mode. Alternatively, you can press the button left of the name of the Style at the top of the Objects and Timeline Panel. The tooltip explains what it does: Return scope to [UserControl].
 
 
Now that you’ve created a Style for one object, you want to apply that to other elements. Select the object and pick the Apply Local Resource option from the Object Menu. Also a less obvious feature of Blend is the Advanced Properties Options Menu that can be reached with the icon to the right of all attributes in the Properties Tab. I mean the small white squares next to input controls. The menu that appears when clicking this small square contains several important options concerning Resources. Because a Style is a Resource, you can apply Style to a series of selected objects this way. The Style property itself is tucked away down in the Miscellaneous category in the Properties Panel. Click the small, white square next to the TextBox and select Local Resource and the specific Style from the menu. The Style input box gets a green border en the small square of the Advanced Properties Options menu also turns green.
 
 

Use Resources

Not only Styles are Resources, you can include a lot of other objects and elements in a ResourceDictionary. These contain a collection of objects that can be reused again and again. This includes Colors and Brushes, but also invisible elements. Styles cannot be applied to every control, because the controls’ Type is recorded and must match. Making use of Resources inside Styles is very efficient. This way the large XAML file is divided in even more small, reusable parts.
 
Create a Resource by opening the Advanced Properties Menu and choose Convert to new Resource… The same dialog as with Styles appears and you can use it to supply the name and scope of the new Resource. Apart from that the Properties Panel has a small button available, especially created to convert a color to a Resource. This also calls a dialog to create a local resource. Color and Brush Resources are also available via the tabs above the ColorPicker control. This ensures Colors and Brushes are chosen quickly and easily.
 
 
Use the Resources Panel
 
 
Arguably the least used Panel in Expression Blend normally sits under the third tab at the right hand site of the screen. This allows access to all Styles and Resources that you have created. There are lists for Resources in the Application (in app.xaml), local Resources (in MainPage.xaml for example) or in the currently selected object. The lists will expand when you click the headers and reveal all Resources present at that Scope. When you open app.xaml, you normally have to edit it in the code editor exclusively. But from the Resources Panel you can edit Resources in Blend Design Mode straight away. Using the small arrow at the right hand side in the bar of a specific Color Resource, a Color Picker control appears in a small pop-up that you can use to modify the Color. Editing Color Gradients gives you a list with colors used and these are editable in the Resources Panel as well. All other Resources are changed by clicking the Edit Resource Button. Then the Resources appear in the Blend ArtBoard as usual, so you can apply the changes using the Properties Panel. The Context Menu of an item in the Resources list allows you to copy, cut, paste and delete specific Resources. 
 
 
Blend includes the XAML markup at the bottom of a file or Resources section, but you can easily determine a specific order yourself, just by dragging Resources to each other that should be together. Less obvious is how fast and simple you can update Local Resources to Application Resources by dragging it up from one list to the other. Blend actually moves the markup code for this Resource from the UserControl file to the app.xaml file. You can do the same for Resources in a UserControl and it works the other way around too.
 
 
When you drag a Resource from the Resource Panel to a specific object on the artboard, you connect to the compatible properties of that object. You can select any property you want from the context menu that appears. If a property does not appear, the Resource is likely of the wrong type. Often you can apply a Resource through a Style property. If you just drop it anywhere on the ArtBoard, Blend will attempt to create a user interface element for it. This can be done because the Resource is of a known type. When your Resource is a Color, Blend will apply this color to the object under the cursor when you let go of the mouse button. When it’s a Brush, Blend will suggest creating a Rectangle, filled with that Color.

Use Resource Dictionaries

Even though a Resource Dictionary is a property of every User Interface Element, you can create loose XAML files that contain only Resources. With the option the merge Resource Dictionaries or even to swap them using code, it is possible to create themes for your application. De organization of your Resources in the different Resource Dictionaries is a matter of personal taste, but you may want to place Colors and Brushes, Fonts, Icons and Illustrations in separate Resource Dictionaries. Also consider placing Styles and Templates for a particular control together in a Resource Dictionary for that control. When you gather Styles for visual elements in a Resource Dictionary you effectively created a style sheet in XAML:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
 
         <!-- Colors -->
<Color x:Key="AppErr">#FFFF0000</Color>
 
<!-- Brushes -->
<SolidColorBrush x:Key="brsAppErr" Color="{StaticResource AppErr}"/>
</ResourceDictionary>
 
At the Application level these Resource Dictionaries are merged:
 
<Application  x:Class="MyApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>  
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ColorsBrushes.xaml"/>
                                <ResourceDictionary Source="Illustrations.xaml"/>
</ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

Using Animations

Only one option is available when you create an animation: entering a name. It is not possible to enter a scope. This is why animations are always generated inside the file in which it is created. Animations are not known to be the most concise XAML and the amount of animations in an application can grow fast. A small piece of C# enables you to set a Target for an animation dynamically. This may seriously reduce the amount of animations, when several different animations actually work on the same object. From the Blend interface this is not possible. As soon as you move an animation to application level, it won’t work anymore, because Silverlight is unable to find the animation. Fortunately this is solved with a little C# too: 
 
Create a helper Class that can find Resources for you. Save this in the project root and call it ResourceLocator.cs:
 
using System;   
using System.Net;   
using System.Windows;   
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 AnimationsAsApplicationResources   
{   
    public static class ResourceLocator   
    {   
        /// <summary>   
        /// Helper method for finding resources located in app.xaml   
        /// </summary>   
        /// <param name="name"></param>   
        /// <returns></returns>   
        public static object FindResource(string name)   
        {   
            if (App.Current.Resources.Contains(name))   
            {   
                return App.Current.Resources[name];   
            }   
            else  
            {   
             FrameworkElement root = 
App.Current.RootVisual as FrameworkElement;
return root.FindName(name); 
            } 
        } 
    } 
}
 
In the Code Behind file of the page with the animation you want to use, add the following code to make an Animation Resource available. Then set the TargetName and start the animation:
 
private void startStoryboard1(object sender, RoutedEventArgs e)   
        {   
            // find the storyboard with helper class:   
            Storyboard Storyboard1Resource = 
                ResourceLocator.FindResource("Storyboard1") as Storyboard;   
            if (Storyboard1Resource != null)   
            {   
                // Set target for storyboard:   
                Storyboard.SetTarget(Storyboard1Resource, Rectangle1);   
                // Begin storyboard:   
                Storyboard1Resource.Begin(); 
            } 
        }
 
It is the helper Class that ensures that the path to the Resource is resolved. When you start it, it is necessary to set its Target using SetTarget. Also, the animation has to be stopped, because while it is still playing its properties cannot be changed. After these changes, don’t forget to move animations to App.xaml.

Using graphical elements

One last way to prevent a large XAML file accumulating is to isolate large quantities of markup that exists because of illustrations or graphical elements. A single graphical element used only once, like a company logo, can easily be transferred to Application Resources. To reuse an element over and over again you can turn it into a Style or Template for a ContentControl. By replacing repeating illustrations with a ContentControl, your markup will become much cleaner. The Style or ControlTemplate is placed in App.xaml or a Resource Dictionary and referred to in the XAML:
 
<ControlTemplate x:Name="TheBullet" TargetType="ContentControl">
    <Grid Width="12" Height="12">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Ellipse x:Name="Bullet" Grid.RowSpan="2" StrokeThickness="0.5" Stroke="#FF800000">
            <Ellipse.Fill>
                <RadialGradientBrush RadiusX="0.67" RadiusY="0.67"
                   Center="0.33,0.22" GradientOrigin="0.33,0.22">
                    <RadialGradientBrush.GradientStops>
                        <GradientStop Color="#FFFFFFFF" Offset="0"/>
                        <GradientStop Color="#FFFF0000" Offset="0.5"/>
                        <GradientStop Color="#FFCC0000" Offset="0.8"/>
                        <GradientStop Color="#FFFF0000" Offset="1"/>
                    </RadialGradientBrush.GradientStops>
                </RadialGradientBrush>
            </Ellipse.Fill>
        </Ellipse>
        <Path x:Name="BulletGlow" Margin="2" Stretch="Fill" Data="F1 M 23.0627,100.787 C 26.3052,100.787 28.9338,103.416 28.9338,106.659C 28.9338,109.901
              26.3052,106.595 23.0627,106.595C 19.8202,106.595 17.1916,109.901
              17.1916,106.659C 17.1916,103.416 19.8202,100.787 23.0627,100.787 Z ">
            <Path.Fill>
                <RadialGradientBrush RadiusX="1.2" RadiusY="0.85"
                    Center="0.33,0.22" GradientOrigin="0.33,0.22">
                    <RadialGradientBrush.GradientStops>
                        <GradientStop Color="#FFFED4D0" Offset="0"/>
                        <GradientStop Color="#FFF27037" Offset="1"/>
                    </RadialGradientBrush.GradientStops>
                </RadialGradientBrush>
            </Path.Fill>
        </Path>
    </Grid>
</ControlTemplate>
 
Apply this ControlTemplate to a ContentControl by pointing its Template property to this Resource. This replaces the use of the Bullet’s extensive XAML three times.
 
<StackPanel>
    <ContentControl x:Name="Bullet1" Template="{StaticResource TheBullet}" />
    <ContentControl x:Name="Bullet2" Template="{StaticResource TheBullet}" />
    <ContentControl x:Name="Bullet3" Template="{StaticResource TheBullet}" />
</StackPanel> 

Use Silverlight 4

In Silverlight 4 improvements are introduced regarding the amount of XAML generated.
In the latest release of Silverlight simple animations are used when no KeyFrames or Easing Functions are needed. This results in much more compact XAML for animations that work exactly the same. When KeyFrames and Easing Functions are necessary, a considerable amount of markup is generated.
The new CompositeTransform simplifies the animation of RenderTransforms significantly by reducing the complexity and fragility of the path to the Transform property in the Storyboard. It also reduces the amount of XAML necessary to reference a specific element in the Storyboard.
 
XAML that is generated when using Blend without thinking too much is becoming messy very quickly. Elements concerning structure and elements necessary for visual design are mixed up. Properties responsible for the look of objects are placed inline, where ideally only Styles should be placed. Use the techniques above to separate structure from looks and gain a much cleaner structure in your XAML-code. Place Colors, Brushes, Animations and large graphical elements apart in Application Resources or a Resource Dictionary and edit them through the Resources Panel. Styles, Resources and Resource Dictionaries are built into the XAML language. But it is your responsibility to keep your XAML as structured as possible. This offers advantages for maintenance of your code and makes it possible that someone else works in the code you created. The Blend user interface offers many opportunities to do that very well.

About the Author

Antoni Dol

Antoni Dol is Senior Designer at Macaw since 1996. He graduated as illustrator at the Gerrit Rietveld Academy of Arts in Amsterdam, studied advertising at the Rotterdam Art Academy and was freelance illustrator for three years. From 1995 onwards, he grew as a web designer with the internet en from 1996 as a designer at Macaw. Antoni is experienced in Windows Presentation Foundation since October 2006 and designed applications in WPF and Silverlight. Antoni works with XAML in WPF and Silverlight projects on a daily basis. He wrote three books in Dutch about XAML, Silverlight 3 and Interaction Design.

#1 Josh on 9.14.2010 at 9:31 AM

You lose me early in this tutorial. I create my object, in this case a circle and then created a new style and give it a simple gradient.

Then I create a new circle and attempt to apply resource to it but apply resource is greyed out for the new object.

I'll keep trying but not sure why I can't reapply.

#2 Suludi on 10.13.2010 at 3:34 PM

Having the same problem as Josh.For example i have a few buttons inside a userControl and Local Resource tab is greyed out.

I had the same problem following one Silverlight book,and now with yours blog.

#3 Antoni Dol on 12.09.2010 at 3:46 PM

Are you still in Style Recording Mode?

Hit the button to the left of the painters’ palette icon in the Breadcrumbs Bar to leave Style Recording Mode. Alternatively, you can press the button left of the name of the Style at the top of the Objects and Timeline Panel. The tooltip explains what it does: Return scope to [UserControl].

Are you applying the style to the same Type of Object?

Styles cannot be applied to every control, because the controls’ Type is recorded and must match.

#4 logo garden on 12.19.2011 at 11:53 AM

Antoni, thanks for the tips b/c I also was having the same problem. It worked for me to hit the button to the left of the name of the style. Expressions Blend can be very touchy, don't you think?

#5 text marketing on 1.04.2012 at 8:29 AM

Thanks for the great help. I too am struggling with the same frustrations with Expressions Blend. Why is it so difficult and sensitive?

#6 Funny funny on 1.05.2012 at 12:32 PM

Interesting, you must have missed that. To Bad for the guy above you... or girl. Prepare for the ice age!

Leave a Comment