Welcome to Pete Brown's 10rem.net

First time here? If you are a developer or are interested in Microsoft tools and technology, please consider subscribing to the latest posts.

You may also be interested in my blog archives, the articles section, or some of my lab projects such as the C64 emulator written in Silverlight.

(hide this)

Getting Started with WPF : Button Control Part 2 – Basic Styling

Pete Brown - 17 February 2010

In my previous post about buttons and content controls, I explained how to do quite a bit of customization using just the content property of a button. That gets you pretty far, but you’re barely tapping into what WPF (and Silverlight) can do.

In this post, we’ll cover styling and and build up the background we’ll need to tackle templating, the backbone of what makes WPF and Silverlight so powerful.

Lookless Controls

In WPF and Silverlight, controls are “lookless”. That is, everything about how they appear is defined in the style and the control template. The code itself just counts on certain elements (Parts) existing in the template. Otherwise, it is ignorant of how the control is presented. The style contains many of the default values for the properties of the control.

That design is what allows you to create listboxes that look more like carousels or menus, and buttons that look completely unlike any normal button. As long as the behavior (the code) is the same, the appearance can be anything you want.

We’ll work our way up to control templates in our next post, but first, let’s jump into styling some buttons.

Styling

Styles in WPF and Silverlight are similar in concept to styles in CSS. They are more powerful in terms of what they can control, but overall the concept is the same.

Like HTML/CSS, the most basic way to set your control’s properties is to do it using regular property statements in the markup. We’ll start there.

Using Properties

The simplest way of setting values on elements is to do it directly in-line, using property assignment in xaml.

In this example, I have three buttons, all with foreground and margin settings.

<Window x:Class="WpfButtonStyling.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="250" Width="400">
    <Grid>
        <StackPanel>
            <Button x:Name="FirstButton"
                    Content="First!"
                    Foreground="Red"
                    Margin="10" />
            <Button x:Name="SecondButton"
                    Content="Second"
                    Foreground="Red"
                    Margin="10" />
            <Button x:Name="ThirdButton"
                    Content="Third"
                    Foreground="Blue"
                    Margin="10" />
        </StackPanel>
    </Grid>
</Window>

The resulting window looks like this:

image

All the buttons share the same margin size, and the first two also have the same foreground color. Rather than specify it each time, it would be better to set up a common style and refer to it from each button. Luckily, that’s really easy to do.

Styles are simply trees of property values for a specific type of control. You can have them inside any element (typically the outermost container like a Window or UserControl), at the application level, or loaded via resource dictionaries.

Local Explicit Styling

For this first look, let’s define our style locally. That means that only elements within the scope of the style can use it. Note that the style is used for all three buttons, but we override the Foreground property on the third button to set it to blue. Locally-provided property values have precedence over those set by a style.

The style itself is set up as a resource in the Window.Resources property of the Window. We provided the style with a key (StandardButton) which may be used in markup to reference it in the button controls. The style also has a TargetType which references the type of control it works on.

<Window x:Class="WpfButtonStyling.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="250" Width="400">
    <Window.Resources>
        <Style x:Key="StandardButton" 
               TargetType="{x:Type Button}">
            <Setter Property="Foreground"
                    Value="Red" />
            <Setter Property="Margin"
                    Value="10" />
        </Style>
    </Window.Resources>
    
    <Grid>
        <StackPanel>
            <Button x:Name="FirstButton"
                    Content="First!"
                    Style="{StaticResource StandardButton}"/>
            <Button x:Name="SecondButton"
                    Content="Second"
                    Style="{StaticResource StandardButton}" />
            <Button x:Name="ThirdButton"
                    Content="Third"
                    Foreground="Blue"
                    Style="{StaticResource StandardButton}" />
        </StackPanel>
    </Grid>
</Window>

The way the style is applied to the buttons is via the StaticResource markup extension. The resulting window looks exactly like the previous one.

Local Implicit Styling

That’s pretty powerful, but it can get tedious to specify the style for each and every button in your application, especially if they’re all going to look exactly the same. Not only that, but it’s error-prone as you could forget to set the style on a button or two, and they’d stick out.

WPF (and Silverlight 4) support the concept of Implicit Styles. These are styles that are based on a type, not a key. Once set, all controls within scope that don’t have an explicit style set will automatically get the implicit style.

To make a style implicit, simply remove its key.

<Window x:Class="WpfButtonStyling.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="250" Width="400">
    <Window.Resources>
        <Style TargetType="{x:Type Button}">
            <Setter Property="Foreground"
                    Value="Red" />
            <Setter Property="Margin"
                    Value="10" />
        </Style>
    </Window.Resources>
    
    <Grid>
        <StackPanel>
            <Button x:Name="FirstButton"
                    Content="First!"/>
            <Button x:Name="SecondButton"
                    Content="Second"/>
            <Button x:Name="ThirdButton"
                    Content="Third"
                    Foreground="Blue"/>
        </StackPanel>
    </Grid>
</Window>

Note how the individual buttons picked up the new style without any additional markup.

Implicit styles are typically used application-wide. Let’s look at how that works.

Application-Wide Styling

So far, the styles we’ve used have been defined in the window’s resources section. To make styles work application-wide, simply include them in App.Xaml.

App.xaml

<Application x:Class="WpfButtonStyling.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml">
    <Application.Resources>

        <Style TargetType="{x:Type Button}">
            <Setter Property="Foreground"
                    Value="Red" />
            <Setter Property="Margin"
                    Value="10" />
        </Style>

    </Application.Resources>
</Application>

Main Window

<Window x:Class="WpfButtonStyling.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="250" Width="400">
   
    <Grid>
        <StackPanel>
            <Button x:Name="FirstButton"
                    Content="First!"/>
            <Button x:Name="SecondButton"
                    Content="Second"/>
            <Button x:Name="ThirdButton"
                    Content="Third"
                    Foreground="Blue"/>
        </StackPanel>
    </Grid>
</Window>

You’ll see that the buttons in our main window still pick up the styles as before. Now, however, buttons in other windows or usercontrols in the project will also pick up the style.

That’s it for the basics of styling. You can also store styles in resource dictionaries that are loaded at runtime as well as use DynamicResource rather than StaticResource (WPF-only) to allow the styles to change during the application’s lifetime. Those techniques all build upon the basics discussed so far.

In our next post in this series, we’ll cover control templates, the bits of xaml that define the elements that make up a control.

       
posted by Pete Brown on Wednesday, February 17, 2010
filed under:        

3 comments for “Getting Started with WPF : Button Control Part 2 – Basic Styling”

  1. Bensays:
    I just went through learning this a week or two ago. I've come up with a decent tip. you can use the "BasedOn" property of a style to inherit from another style. a good use for this is to define an explicit style high up in your application hierarchy (either at the window level or the application level) and then define implicit styles at the StackPanel level, or the Grid level that are BasedOn that high level style. In this way you can use implicit styles in the particular stretches of markup where they make sense without forcing your entire application to use a particular implicit style.
  2. Mark Struiksays:
    Is it possible to get the disigner too load a default theme in a way? I have an assembly containing the user controlls, one containing the themes as dictionaries. And the main app where I switch the dictionary on theme change in the app.xaml. This works great for the main app. But th designer doesn't work in my usercontroll assembly. I can get it to work by assigning a hard reference too a styleset but then I can't overwrite it anymore in the main app.

    Twitter: @misticrain

Comment on this Post

Remember me

1 trackback for “Getting Started with WPF : Button Control Part 2 – Basic Styling”

  1. uberVU - social commentssays:
    This post was mentioned on Twitter by Pete_Brown: Blogged: Getting started with WPF: Button control part 2: Basic Styling http://bit.ly/aKo0oV #wpf