Defining Style Resources

The simplest form of styling your user interface is to assign values to properties exposed by controls, using attribute syntax. However, this will very soon lead to your XAML becoming an unmaintainable mess. Doing so will result in your XAML files becoming unwieldy, complex, and hard to read; and any necessary styling changes will often need to be made in numerous places within the application—essentially, you will have spaghetti XAML code.

The answer to this problem is to use style resources. Defining and using style resources has numerous advantages. If we want to change the styling of all our TextBox controls, we only need to set the value in one place, and it will automatically be applied to all the controls that reference that style. This simplifies the XAML by removing the need to repeatedly apply the same property values on each control. It also creates a clearer separation between your control definitions and their appearance.

You could consider style resources to be similar to CSS styles in traditional HTML–based web development. With CSS, you can define a style specifying various property values in your CSS file or in your HTML page header and apply that style to HTML elements by assigning the name of the style to their class property. Alternatively, you can define a style that specifies the values that the properties on all elements of a given type should automatically use. You can then override the property values defined in these styles by assigning different property values directly on the elements themselves.

Styling in Silverlight works in a similar fashion. Style resources can be defined in a resource dictionary or within a XAML file itself and applied to controls by pointing their Style properties to the style resource, using the StaticResource markup extension. Alternatively, you can exclude the key from a style resource definition, and all the controls of the given type will automatically use that style (known as implicit styling).

images Note Unlike CSS, style resources are specific to their target control type, meaning you cannot create a style that defines a set of property values to be used by both TextBox controls and ComboBox controls, for example.

We have already discussed the concept of style resources in Chapter 2, which demonstrated how you could define a group of property values commonly assigned to a type of control as a style resource and then apply that to the Style property of any controls that use it. However, we will start with a quick overview and move on to discuss some more advanced styling features.

Defining a Style Resource

There are two types of style resources: explicit and implicit. Let's take a look at each of these in turn.

Explicit Styles

Let's say we have multiple TextBox controls in our project that use a common set of property values. Instead of assigning the same property values to each control, like this

<TextBox Name="FirstNameField" Margin="2" Background="LemonChiffon" Grid.Row="0" />
<TextBox Name="LastNameField" Margin="2" Background="LemonChiffon" Grid.Row="1" />
<TextBox Name="CompanyField" Margin="2" Background="LemonChiffon" Grid.Row="2" />

we can, instead, define these properties as a style resource:

<Style x:Key="UserFieldsStyle" TargetType="TextBox">
    <Setter Property="Margin" Value="2" />
    <Setter Property="Background" Value="LemonChiffon" />
</Style>

When defining our style resource, we are giving it a unique key to reference it using the x:Key attached property from the XAML namespace and specifying the type of control it can be applied to using the TargetType property. After that, it's a case of creating a Setter element for each property you want to specify a value for and providing it the name of the property and its corresponding value. We can now apply this style to the Style property on our controls, using the StaticResource XAML markup extension. The StaticResource markup extension is used to reference the style resource by using the key of the style resource to find it.

<TextBox Name="FirstNameField" Grid.Row="0" Style="{StaticResource UserFieldsStyle}" />
<TextBox Name="LastNameField" Grid.Row="1" Style="{StaticResource UserFieldsStyle}" />
<TextBox Name="CompanyField" Grid.Row="2" Style="{StaticResource UserFieldsStyle}" />

images Note You can override the values from the style resource by simply applying alternate property values directly to the control itself, via inline styles.

This is a process of explicitly assigning a style to a control. We gave the style resource a key, and explicitly assigned that style to a control.

Implicit Styles

Alternatively, you may want to implicitly assign a style resource to all controls within a given scope. This is possible using the implicit styles functionality introduced in Silverlight 4. Simply omit the key when defining a style resource, and all controls of the control type that the style targets within the scope of the resource will automatically use that style. For example, if you define the previous style resource, without a key defined, at a view level—for example, in Page.Resources or UserControl.Resources—the style will be automatically applied to all of the TextBox controls within that view. If a style resource is defined at the application level, it will used by controls application-wide, which is a typical scenario when creating themes that will be discussed later in this chapter.

Let's revisit the example that was used to demonstrate explicit styles and convert it to use implicit styles now. Start by removing the key from the style definition:

<Style TargetType="TextBox">
    <Setter Property="Margin" Value="2" />
    <Setter Property="Background" Value="LemonChiffon" />
</Style>

Now, all your TextBox controls within the scope of this implicit style will automatically use the style without actually needing any reference to the style:

<TextBox Name="FirstNameField" Grid.Row="0" />
<TextBox Name="LastNameField" Grid.Row="1" />
<TextBox Name="CompanyField" Grid.Row="2" />

images Note Microsoft recommends that you avoid assigning values to properties in style resources where the property is defining behavior (as opposed to appearance).

Defining Style Resources in the Object Hierarchy

Style resources can be defined at various levels of the object hierarchy, and the level at which a style is defined provides its scope. Let's look at the most common locations for defining style resources in your project.

At the Control Level

If you define a style resource in the Resources property of any element in the control hierarchy, it will be available for use by the descendents of that element. This isn't recommended however, due to potential maintainability issues—specifically because of confusion as to where a style resource definition can be found.

At the View Level

If style resources are defined at the view level in Page.Resources or UserControl.Resources in a XAML file, they will be available for use by all the controls in that view.

At the Application Level

You can define application-wide style resources on the Application.Resources property of the App.xaml file.

As a Resource Dictionary

Style resources defined at the application level are often defined in a resource dictionary and merged into the application's resources. This strategy has the following benefits:

  • Keeps the style resource definitions from clogging up the App.xaml file
  • Enables the style resources to be reused among projects
  • Enables different style resources dictionaries to be easily swapped in and out
  • Enables your application to be themed

The best example of this strategy is already implemented in the project you've generated from the Silverlight Business Application project template. All style resources are defined in a resource dictionary called Styles.xaml that is found in the Assets folder. This file is then merged into the application's resources, in the App.xaml file, like so:

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

images Note Multiple resource dictionaries can be merged into a single Resources property. Therefore, you can maintain a logical separation between your various style resources, avoiding resource dictionaries becoming too large and complex and enabling multiple developers on the project to maintain styles at the same time. If a style is defined in more than one resource dictionary, the last one to be merged will used. If you have two implicit styles targeting the same control, the property setters won't be merged into a single style, but only the last style will be used.

Alternatively, if you have only a single resource dictionary to merge, you can simply assign the resource dictionary to Application.Resources:

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

You can create a new resource dictionary by adding a new item to your project and selecting the Silverlight Resource Dictionary project template. This will leave you with an empty resource dictionary structure to which you can add your styles. For example, here is the UserFieldsStyle style resource we created earlier, defined in a resource dictionary:

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

    <Style x:Key="UserFieldsStyle" TargetType="TextBox">
        <Setter Property="Margin" Value="2" />
        <Setter Property="Background" Value="LemonChiffon" />
    </Style>
</ResourceDictionary>
As a Resource Dictionary in a Referenced Assembly

Themes are often defined in a resource dictionary, and defining this resource dictionary in its own assem-bly can be useful so that you can maintain the theme in a single location and use it in multiple projects.

Add a reference to the assembly containing the resource dictionary to use to your project. You can then merge the resource dictionary into your application's resources as previously demonstrated. However, the path to the view needs to be of the form "/[assembly];component/[viewpath]". For example, if the ThemeStyles.xaml view existed in a referenced assembly named MyTheme.dll, the path to navigate to it would be "/MyTheme;component/ThemeStyles.xaml".

<Application.Resources>
    <ResourceDictionary Source="/MyTheme;component/ThemeStyles.xaml" />
</Application.Resources>
In Generic.xaml

Custom controls generally have their styles and control templates defined in a resource dictionary named Generic.xaml, which does not need to be merged into any Resource property but must be placed under the Themes folder in the project where the corresponding controls are defined. This will be discussed in Chapter 12.

Storing Complex Property Values in Styles

It's worth noting that complex values can be stored in styles. For example, when defining a gradient on a property in a style, you use property element syntax to define the gradient the same way as you would if assigning the gradient directly on the control itself:

<Style x:Key="UserFieldsStyle" TargetType="Control">
    <Setter Property="Margin" Value="2" />
    <Setter Property="Background">
        <Setter.Value>
            <LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
                <GradientStop Color="LemonChiffon" Offset="0" />
                <GradientStop Color="#FFFFFFCD" Offset="1" />
            </LinearGradientBrush>
        </Setter.Value>
    </Setter>
</Style>

Naming Style Resources

As a part of our design process, we need to look further than just how each control type will be styled and design and name styles based on their purpose within the application rather than what they consist of or the type of control they will be applied to. For example, you might have a TextBlock style resource that you want to use throughout your application to make the text bold, with a font size of 12 points, and colored navy. How should you name this style resource? Maybe TextBlockStyle, BoldNavy12ptStyle, PageHeaderStyle, or PageHeaderTextBlockStyle?

From both a management and a visual design perspective, PageHeaderStyle or PageHeaderTextBlockStyle would be the best way to name the style resource, because either of these names makes it easy to see what the purpose of each style is when navigating the style resource definitions. Also, if you are designing a new theme for the application or plan to support multiple themes, this naming scheme makes much more sense, because you are linking each style to a purpose rather than linking each style to how it is rendered on screen.

So even if two different definitions of a style resource have exactly the same property values, it is generally still better to define them as separate style resources. This may result in multiple styles containing the same property values but provides better support for future restyling.

Inheriting Style Resources

Only a single style resource can be applied to a control, which may initially seem somewhat limiting when you are designing your style resources. For example, you may wish to define some property values in a base style resource common to most or all controls of a given type and then define another style resource containing additional property values to be applied to only some controls of that type.

While you may not be able to apply both those style resources to a control, you can have your new style resource inherit the property value definitions from the base style resource, which will serve the same purpose. This is achieved using the BasedOn property of the Style, which you can point to another style resource that this style will inherit from. Because you are pointing to a resource, you need to use the StaticResource markup extension. For example, say we have this style resource that we want to use as our base:

<Style x:Key="UserFieldsStyleBase" TargetType="TextBox">
    <Setter Property="Margin" Value="2" />
    <Setter Property="Background" Value="LemonChiffon" />
</Style>

When defining a new style resource that should be based on this one, we can inherit from it using the BasedOn property, like so:

<Style x:Key="UserFieldsStyle" TargetType="TextBox"
       BasedOn="{StaticResource UserFieldsStyleBase}">
    <Setter Property="TextAlignment" Value="Right" />
</Style>

images Note A style resource can only be based on a single style, but that style can be based on another style, and so on.

Not only can you inherit the property value definitions from a base style resource using this method but you can also override some of those property value definitions. For example, despite the Background property having a value of LemonChiffon in the base style, we've overridden that property in this style and assigned it a value of White instead:

<Style x:Key="UserFieldsStyle" TargetType="TextBox"
       BasedOn="{StaticResource UserFieldsStyleBase}">
    <Setter Property="Background" Value="White" />
</Style>

If you have a style resource that inherits a property value, but you want remove that property from the style, you can simply null its value like so:

<Setter Property="Background" Value="{x:Null}" />

images Note The target control type from which you inherit a style must match that of the new style. For example, you cannot have a style targeting the TextBox control inherit from a style targeting the ComboBox control. You can, however, have a style that inherits from a style targeting one of its base classes. For example, a style targeting the TextBox control can inherit from a style targeting the Control class.

Styling Constraints

There are a few issues that you should be aware of when defining styles:

  • Only a single style resource can be assigned to a control, and any further property values that need to be applied must be applied inline on the control itself.
  • Styles cannot be applied to controls of different types. Each style has a single control type that it applies to, meaning that you cannot have a TextBox and a ComboBox control reference the same style. You can assign the target type to be a class common to both those controls, such as Control, but you will often find that the properties you wish to define values for will not exist on that base class, and therefore, the project will not compile. Note that attempting this with implicit styles will not work. The type of controls that will automatically use implicit styles must match the given target type of the style exactly; otherwise, the style will not be applied.
  • Once you have assigned a style to a control, any implicit style that the control may have otherwise used will no longer be used by this control.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset