This is the tenth post in my series, “31 Days of Silverlight.” Can’t believe I’m already 1/3 of the way through this. Today’s article focuses on a common problem in nearly all development. For web developers, I equate this to Cascading Style Sheets. We are going to take an overly marked-up XAML page, and externalize the common attributes into a Style that can be applied over and over to similar elements. The other great benefit of Styles is that when we want to change something (don’t tell me you never get changes…), you can make that change in one place, instead of having to hunt through multiple lines of multiple files.
A Simple Web Form
The first thing I want to do in this demo is create a simple address form. We’ll get it looking the way we want, and then we can extract those properties that are common to create our Styles. Here’s our initial form, in all its markup glory:
<UserControl x:Class="SilverlightStyling.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<TextBlock Text="First Name:" Grid.Column="0" Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,10,0" />
<TextBlock Text="Last Name:" Grid.Column="0" Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,10,0" />
<TextBlock Text="Address:" Grid.Column="0" Grid.Row="2" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,10,0" />
<TextBlock Text="City, State, Zip:" Grid.Column="0" Grid.Row="3" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,10,0" />
<TextBlock Text="Email Address:" Grid.Column="0" Grid.Row="4" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,10,0" FontWeight="Bold" />
<TextBox x:Name="FirstName" Text="Jeff" Grid.Column="1" Grid.Row="0" Height="25" Width="190" HorizontalAlignment="Left" />
<TextBox x:Name="LastName" Text="Blankenburg" Grid.Column="1" Grid.Row="1" Height="25" Width="190" HorizontalAlignment="Left" />
<TextBox x:Name="Address" Text="8800 Lyra Ave. #400" Grid.Column="1" Grid.Row="2" Height="25" Width="190" HorizontalAlignment="Left" />
<TextBox x:Name="CityStateZip" Text="Columbus, OH 43240" Grid.Column="1" Grid.Row="3" Height="25" Width="190" HorizontalAlignment="Left" />
<TextBox x:Name="Email" Text="" Grid.Column="1" Grid.Row="4" Height="25" Width="190" HorizontalAlignment="Left" />
<Button x:Name="Clicky" Content="Submit" Grid.Column="1" Grid.Row="5" Height="25" Width="100" HorizontalAlignment="Left" />
</Grid>
</UserControl>
You can see that if we had written all of that code by hand, we’d be repeating ourselves over and over again. Much like in CSS, if we have common attributes across elements, we should define them in one place, and reference them as a style. If you look at our TextBlock elements, each of them has a VerticalAlignment, HorizontalAlignment, and Margin. We can take all of that XAML away and make it a style. I’ll also play with colors and fonts once the style has been created.
Creating a style in app.xaml
Our styles are stored in our app.xaml file. If you open yours up, you’ll notice that there’s nearly nothing in there. Inside the <Application.Resources> block, we’re going to add a <Style> element. Each Style has a TargetType, which is the type of XAML element we’ll be styling. In this example, we’re going to style the TextBlock element. We will also give it a name (in this syntax, a x:Key attribute) so that we have a way to refer to it in our XAML later. Here’s the contents of my app.xaml file:
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SilverlightStyling.App"
>
<Application.Resources>
<Style TargetType="TextBlock" x:Key="FormLabel">
</Style>
</Application.Resources>
</Application>
Adding style properties
Now we need to actually add some style properties to our Style. We do that with the <Setter> element. Think of each one as a name-value pairing. We can set any of the properties of a XAML element from here, above and beyond even the asthetics of looks and colors. In this case, I am going to take the VerticalAlignment, HorizontalAlignment, and Margin properties for my TextBlocks, and put them in my Style element instead. Here’s the newly modified app.xaml file:
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SilverlightStyling.App"
>
<Application.Resources>
<Style TargetType="TextBlock" x:Key="FormLabel">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Right" />
<Setter Property="Margin" Value="0,0,10,0" />
</Style>
</Application.Resources>
</Application>
We will also take those properties out of the TextBlock elements, or this whole process would be a little silly, right? Here’s the XAML for just one of the TextBlock elements, with those properties removed, and a reference to our style included:
<TextBlock Text="First Name:" Grid.Column="0" Grid.Row="0" Style="{StaticResource FormLabel}" />
Our final XAML file
After we remove all of the duplicated properties from our elements, we have a much smaller, more compact XAML file. The interface still looks exactly the same, but we have much more flexibility and manageability going forward. Here’s the final XAML file:
<UserControl x:Class="SilverlightStyling.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<TextBlock Text="First Name:" Grid.Row="0" Style="{StaticResource FormLabel}" />
<TextBlock Text="Last Name:" Grid.Row="1" Style="{StaticResource FormLabel}" />
<TextBlock Text="Address:" Grid.Row="2" Style="{StaticResource FormLabel}" />
<TextBlock Text="City, State, Zip:" Grid.Row="3" Style="{StaticResource FormLabel}" />
<TextBlock Text="Email Address:" Grid.Row="4" Style="{StaticResource FormLabel}" FontWeight="Bold" />
<TextBox x:Name="FirstName" Text="Jeff" Grid.Row="0" Style="{StaticResource TextBox}" />
<TextBox x:Name="LastName" Text="Blankenburg" Grid.Row="1" Style="{StaticResource TextBox}" />
<TextBox x:Name="Address" Text="8800 Lyra Ave. #400" Grid.Row="2" Style="{StaticResource TextBox}" />
<TextBox x:Name="CityStateZip" Text="Columbus, OH 43240" Grid.Row="3" Style="{StaticResource TextBox}" />
<TextBox x:Name="Email" Text="" Grid.Row="4" Style="{StaticResource TextBox}" />
<Button x:Name="Clicky" Content="Submit" Grid.Column="1" Grid.Row="5" Height="25" Width="100" HorizontalAlignment="Left" />
</Grid>
</UserControl>
Our final app.xaml file
Here’s our final app.xaml file. You’ll see that we created two different styles. One for the TextBlocks, and one for the TextBoxes. I also added a different font size and foreground color to the TextBlock style, so that you can see those change as well. Here’s the code:
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SilverlightStyling.App"
>
<Application.Resources>
<Style TargetType="TextBlock" x:Key="FormLabel">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Right" />
<Setter Property="Margin" Value="0,0,10,0" />
<Setter Property="FontSize" Value="20" />
<Setter Property="Foreground" Value="Blue" />
</Style>
<Style TargetType="TextBox" x:Key="TextBox">
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Height" Value="25" />
<Setter Property="Width" Value="190" />
<Setter Property="Grid.Column" Value="1" />
</Style>
</Application.Resources>
</Application>
Summary
Today, we created a small form that has some very similar elements on it. Instead of styling each individual element, we externalized the common properties of those elements into Styles that can be reused over and over. The example application is running beneath this paragraph. If you can’t see the Silverlight Styling demo below, click here to see it. To download the source code for this demo, click here to download the Silverlight Styling demo.
Leave a Reply