An issue that many WPF developers come across is the need to reuse Xaml across several different Xaml files. For example snippet 1 shows some Xaml I want to reuse in several other Xaml files.   I could just cut and paste the Label and every ComboBox controls, but that would result in a lot of bloat and when I wanted to change the look of my Label or ComboBox I would have to update ever instance of the controls.

Snippet 1. – Window1.xaml

<Window x:Class="WPFRefactoring.Window1" xmlns="http://schemas.microsoft.com/winfx/avalon/2005" xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005" Title="WPFRefactoring">
    <Grid>
        <StackPanel Orientation="Horizontal">
            <Label Foreground="Blue" FontSize="20" FontFamily="Edwardian Script ITC">Can you read this font?</Label>
            <ComboBox Name="comboBox1" Background="Tomato">
                <TextBlock Text="Yes"/>
                <TextBlock Text="No"/>
                <TextBlock Text="What's the questions?"/>
            </ComboBox>
        </StackPanel>
    </Grid>
</Window>
 


Figure 1. – Window1
 
 One
 
WPF provides a few different ways to mitigate this problem. The first is to use a local style as shown in snippet 2. I simply migrate the properties that I want to be reused into a style for the control.
 

Snippet 2. – Window1.xaml using Styles.

<Window x:Class="WPFRefactoring.Window1" xmlns="http://schemas.microsoft.com/winfx/avalon/2005" xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005" Title="WPFRefactoring">
    <Grid>
        <Grid.Resources>
            <Style TargetType="{x:Type Label}">
                <Setter Property="Foreground" Value="Blue"/>
                <Setter Property="FontSize" Value="20"/>
                <Setter Property="FontFamily" Value="Edwardian Script ITC"/>
            </Style>
            <Style TargetType="{x:Type ComboBox}">
                <Setter Property="Background" Value="Tomato"/>
            </Style>
        </Grid.Resources>
        <StackPanel Orientation="Horizontal">
            <Label>Can you read this font?</Label>
            <ComboBox>
                <TextBlock Text="Yes"/>
                <TextBlock Text="No"/>
                <TextBlock Text="What's the questions?"/>
            </ComboBox>
            <Label Content="This Label uses the Style too."/>
        </StackPanel>
    </Grid>
</Window>


Figure 2. - Window1

Two

This works well as I didn’t have to write the properties for the second label I added , but I want every Label and every ComboBox in my application to look this way not just those displayed in Window1.xaml. To do this I need put my style in the <Application.Resources> section of their MyApp.xaml file.   This is shown in snippet 3. and the change to Window1.xaml is shown in snippet 4. I simply cut and pasted the styles from Window1.xaml into MyApp.xaml and deleted the resource section from Window1.xaml.

Snippet 3. – MyApp.xaml

<Application x:Class="WPFRefactoring.MyApp" xmlns="http://schemas.microsoft.com/winfx/avalon/2005" xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005" StartupUri="Window1.xaml">
    <Application.Resources>
        <Style TargetType="{x:Type Label}">
            <Setter Property="Foreground" Value="Blue"/>
            <Setter Property="FontSize" Value="20"/>
            <Setter Property="FontFamily" Value="Edwardian Script ITC"/>
        </Style>
            <Style TargetType="{x:Type ComboBox}">
            <Setter Property="Background" Value="Tomato"/>
        </Style>
    </Application.Resources>
</Application>

Snippet 4. - Window1.xaml

<Window x:Class="WPFRefactoring.Window1" xmlns="http://schemas.microsoft.com/winfx/avalon/2005" xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005" Title="WPFRefactoring">
    <Grid>
        <StackPanel Orientation="Horizontal">
            <Label>Can you read this font?</Label>
            <ComboBox>
                <TextBlock Text="Yes"/>
                <TextBlock Text="No"/>
                <TextBlock Text="What's the questions?"/>
            </ComboBox>
            <Label Content="This Label uses the Style too."/>
        </StackPanel>
    </Grid>
</Window>


Not only does this allow me to reuse the Label and ComboBox Styles throughout my application, but it makes my Window1.Xaml file easier to read. Snippet 5 shows a new Xaml file that makes use of the same style. Notice that the writer of Window2.xaml doesn’t need to know about my application level styles.
 

Snippet 5. – Window2.xaml

<Window x:Class="WPFRefactoring.Window2" xmlns="http://schemas.microsoft.com/winfx/avalon/2005" xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005" Title="WPFRefactoring">
    <Canvas>
        <StackPanel Orientation="Horizontal">
            <Label>Style Still Works</Label>
            <ComboBox>Same Here</ComboBox>
        </StackPanel>
    </Canvas>
</Window>


Figure 3. – Window 2

Three


What if I wanted to have all of the dialogs in my application use a different style then the application level style? I could once again copy and paste, ever Label and every ComboBox style section, but this would still run into the update and bloat problem. The solution is to create a ResourceDictionary item and place my dialog styles in it. Then reference my style in my dialogs.
Snippet 6 shows my ResourceDictionary, note that it looks very similar to my application resources section in MyApp.xaml, but every Style must use a key, because this is a dictionary.
 
Snippet 6. – MyResourceDictionary.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/avalon/2005" xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005">
    <Style x:Key="MyLabelStyle" TargetType="{x:Type Label}">
        <Setter Property="Foreground" Value="Green"/>
        <Setter Property="FontSize" Value="20"/>
        <Setter Property="FontFamily" Value="Tahoma"/>
    </Style>
    <Style x:Key="MyComboBoxStyle" TargetType="{x:Type ComboBox}">
        <Setter Property="Background" Value="Yellow"/>
    </Style>
</ResourceDictionary>


Snippet 7. – MyApp.xaml

<Application x:Class="WPFRefactoring.MyApp" xmlns="http://schemas.microsoft.com/winfx/avalon/2005" xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005" StartupUri="Dialog.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="MyResourceDictionary.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
        <Style TargetType="{x:Type Label}">
            <Setter Property="Foreground" Value="Blue"/>
            <Setter Property="FontSize" Value="20"/>
            <Setter Property="FontFamily" Value="Edwardian Script ITC"/>
        </Style>
        <Style TargetType="{x:Type ComboBox}">
            <Setter Property="Background" Value="Tomato"/>
        </Style>
    </Application.Resources>
</Application>


Snippet 8. – Dialog.xaml

<Window x:Class="WPFRefactoring.Dialog" xmlns="http://schemas.microsoft.com/winfx/avalon/2005" xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005" Title="WPFRefactoring">
    <Grid>
        <Grid.Resources>
            <Style TargetType="{x:Type Label}" BasedOn="{StaticResource MyLabelStyle}"/>
        </Grid.Resources>
        <StackPanel Width="250">
            <Label>Resources are fun.</Label>
            <ComboBox>Application Level ComboBox</ComboBox>
            <ComboBox Style="{StaticResource MyComboBoxStyle}">My Overriden Style</ComboBox>
        </StackPanel>
    </Grid>
</Window>


Figure 4. – Dialog

Four


Note that in snippet 8 I show two different ways to reference the styles defined in the MyResourceDictionary.xaml file. If I planned on having multiple Label’s or ComboBox’s or I wanted to use both the application level style and the style in my ResourceDictionary I would define a new style that is based on the style in my ResourceDictionary as shown in snippet 9.

Snippet 9.

<Grid.Resources>
    <Style TargetType="{x:Type Label}" BasedOn="{StaticResource MyLabelStyle}"/>
</Grid.Resources>

If I was only going to use a style once in a file I would just reference the style directly.

Snippet 10.

<ComboBox Style="{StaticResource MyComboBoxStyle}">My Overriden Style</ComboBox>

Styles are a great way to reuse Xaml in a WPF application. They make it easier to update the look of an application, reduce the size of an application and reduce the complexity of reading xaml files.