Click here to Skip to main content
15,861,168 members
Articles / Desktop Programming / WPF

Skinning a WPF App in Blend

Rate me:
Please Sign up or sign in to vote.
4.87/5 (36 votes)
23 Jan 2011CPOL11 min read 83.3K   1.9K   82   19
Learn how to skin a WPF application in Expression Blend.

Introduction

In this tutorial, I will show you how to skin a WPF application in Expression Blend. The application you'll create will have a very simple UI, but the concepts you'll learn will enable you to skin WPF applications with more expansive user interfaces.

Background

Skinning is the process of adding functionality to an application that enables the user to change its look and feel at runtime. Skinning your WPF application involves taking into account certain factors which you'll familiarize yourself with as you go along.

Design

Let’s start skinning:

  1. Start Expression Blend and create a new WPF project named Skinning. Ensure that the Language is set to Visual Basic in the Language combo box.
  2. Select the Window element in Objects and Timeline, and in the Layout section of the Properties panel, set the width to 400 and height to 300.
  3. Select the Rectangle tool from the Toolbox, and draw out a rectangle on the window. Set the rectangle’s Vertical Alignment to top.
  4. Image01.jpg

    Image02.jpg

  5. Rename the rectangle as Header and give it a blue gradient Fill. Set its Stroke to No brush.
  6. Image03.jpg

  7. Select the Window element and in the Brushes section of the Properties panel, set its Background to a gradient brush.
  8. Image04.jpg

  9. Select the Button tool and draw a button in the Window element.
  10. Image05.jpg

We will skin our app next by changing the current blue look to red. Skinning involves making use of ResourceDictionarys that contain the different look and feel that you'd want for your application. A ResourceDictionary is basically a collection of resources. A resource can be any of the properties of an object, or in the case of a control like a button, a style or a template. For a property to change when you add a new ResourceDictionary, it must be assigned a DynamicResource. A DynamicResource changes at runtime when you switch from one ResourceDictionary to another.

If you take a look at the XAML code for the application, you will notice that there are no DynamicResources assigned to any of the properties of the elements in the application. This shall change as we go along.

ResourceDictionaries and Resources

In the following steps, we shall create ResourceDictionarys and resources.

  1. Click on the Resources tab to open the Resources panel, and click on the Create new resource dictionary button.
  2. Image06.jpg

  3. In the New Item dialog, change the name of the new ResourceDictionary to BlueSkin.xaml. Click on OK. BlueSkin.xaml is added to the list in the Resources panel.
  4. Select the Window element in Objects and Timeline, and open the Properties panel.
  5. Click on the ‘Advanced options’ button that is next to the Background property in the Brushes section. Select Convert to New Resource from the context menu. This opens the Create Brush Resource dialog.
  6. In the Create Brush Resource dialog, change the name to WindowBackground and select the Resource Dictionary option button. Ensure that you have BlueSkin.xaml as the intended target in the combo box. Click on OK. If you now switch to the XAML view, you will notice that the Background property of the Window element is assigned a DynamicResource named WindowBackground.
  7. Select the rectangle we added. In the Properties panel, click on the Advanced options button of the Fill property and select Convert to New Resource from the context menu.
  8. Name the new resource as ‘HeaderFill’ and select the ‘Resource dictionary’ option button. Click on Ok.
  9. Select the Resources tab to open the Resources panel. Create a new Resource Dictionary and name it RedSkin.xaml.
  10. Select the Window element and change the gradient brush of its Background to a reddish gradient.
  11. Image07.jpg

  12. Click on the ‘Advanced options’ button of the Background property and select Convert to new Resource from the context menu.
  13. In the Create Brush Resource dialog, change the name to WindowBackground and select the Resource dictionary option button. Select RedSkin.xaml from the combo box and click on OK. Ignore the warning. If you now look in the Resources panel and expand both BlueSkin and RedSkin.xaml, you will notice that both resource dictionaries have resources with the same name.
  14. Image08.jpg

    Since WindowBackground in BlueSkin is a DynamicResource, it will be swapped with WindowBackground in RedSkin when we change the resource dictionary. If the names were different, there would be no change in the background color since your application wouldn't know which resource to apply from the new resource dictionary.

  15. Select Header in Objects and Timeline, and give its Fill a red gradient.
  16. Image09.jpg

  17. Click on the ‘Advanced options’ button of the Fill property and select Convert to New Resource from the context menu.
  18. In the ‘Create Brush Resource’ dialog, change the name to HeaderFill and select the Resource dictionary option button. Select RedSkin.xaml from the combo box and click on OK.

Now that we have completed creating our Resource Dictionaries, let's add the necessary coding to enable us to switch to the red skin at runtime.

Coding

  1. Select the button we added to our application, and in the Properties panel, click on the Events button.
  2. Image10.jpg

  3. In the Click event textbox, type ‘Btn1_Click’ and press Enter. Blend’s code editor opens for you to add the necessary code for the button’s click event.
  4. Image11.jpg

  5. In the Btn1_Click event, type in the following code:
  6. VB
    Dim RedSkin as New ResourceDictionary
    RedSkin.Source = New Uri("RedSkin.xaml", UriKind.Relative)
    Me.Resources.MergedDictionaries.Clear()
    Me.Resources.MergedDictionaries.Add(RedSkin)

    The code above creates a new resource dictionary named RedSkin and assigns its source property the resource dictionary RedSkin.xaml that we created earlier. We then clear the MergedDictionaries collection and add a new resource dictionary. MergedDictionaries is a collection of ResourceDictionary objects. If you have an application where you want to maintain the link to an existing resource dictionary, then avoid clearing the MergedDictionaries collection, and instead of using the Add method, type in the following code:

    VB
    Me.Resources.MergedDictionaries(0) = RedSkin
    

    This code places the resource dictionary in the first slot of the MergedDictionaries collection.

  7. Select the Resource panel tab and expand App.xaml.
  8. Since our application is currently linked to RedSkin.xaml, we’ll remove this link. Right click ‘Linked To: RedSkin.xaml’ and select Delete from the context menu. Click on Yes in the resulting dialog box.
  9. Run the application. Click on the button. Notice that the interface changes to a reddish look.
  10. Close the application.

So far, we have managed to change the look of some of the elements in our application. The button object still looks the same even after we switch skins. Changing the look of a control is slightly different than changing the look of a shape object like a rectangle or ellipse. To change the look of a control object, we have to work with either styles or templates.

Styles allow us to change the look of a control, but limit us since we can’t directly access the elements that make up the control. Templates, on the other hand, allow us to directly manipulate the elements that make up a control. In a template, you can add, delete, or modify the elements that make up the overall structure of a control. Therefore, when skinning a control, you can choose to work with either styles or templates.

Skinning a Control Object

In the following steps, we shall skin our button control by using templates:

  1. Select the button object. Right click the button and select Edit Template > Create Empty.
  2. In the ‘Create ControlTemplate Resource’ dialog, leave the name as is, and select the Resource dictionary option button. BlueSkin.xaml should be the only value in the combo box as we deleted the link to RedSkin. Click on OK.
  3. Zoom in on the empty Control Template.
  4. Draw a rectangle in the empty grid, and then right click it and select Auto Size > Fill. The rectangle should fill the whole grid.
  5. Rename the rectangle as BtnBackground and give it rounded corners.
  6. In the Properties panel, ensure that the Properties button, and not the Events button, is active. Change StrokeThickness to 2 and change the stroke color to a white solid brush.
  7. Select Fill and change it to a blue gradient brush.
  8. Image12.jpg

  9. Select the Assets button in the toolbox, and select the ContentPresenter in the Controls section of the Assets window. ContentPresenter is added to the toolbox.
  10. Double click on the ContentPresenter tool in the toolbox to add it to the control’s grid. Set its Horizontal and Vertical alignments to center.
  11. Draw out another rectangle. Set its stroke to No Brush, then adjust it to look like the following image. Turn off snapping to snaplines if it’s giving you a hard time.
  12. Image13.jpg

  13. Change both gradient stops to white, and adjust the alpha property of the last gradient stop to zero.
  14. Image14.jpg

    Image15.jpg

  15. In the Objects and Timeline panel, click on the Up One Level button to return back to the Window.
  16. Image16.jpg

  17. With the button object is selected, change its Content property to ‘Red’ and press Enter. Then change its Foreground property to White. Save the project.
  18. Image17.jpg

  19. In the Resources panel, right click App.xaml and select Link to ResourceDictionary > RedSkin.xaml. Linking to RedSkin makes it visible in the Resource dictionary combobox of the ‘Create ControlTemplate Resource’ dialog.
  20. Select the button. Right click the button and select Edit Template > Edit a Copy.
  21. In the ‘Create ControlTemplate Resource’ dialog, change the name to ButtonControlTemplate1 and select the Resource dictionary option button and RedSkin.xaml from the combo box. Click on OK.
  22. In the button control template, change the Fill of BtnBackground to a red gradient.
  23. Image18.jpg

  24. Return back to the main window. Delete the link to RedSkin.xaml in the App.xaml section of the Resources panel. Click Yes in the resulting dialog.
  25. Run the project and click on the button. Notice now that all the elements in the application are skinned. A bit of animation would have served our button well to make it look like it’s lighting up during mouse over events, but you can do that in your free time.

It isn’t quite interesting that we can’t switch between our two skins, so let’s enable that.

  1. Stop the application if you haven’t done so.
  2. Select the button object and copy-paste a new button onto your Window.
  3. Drag it and place it below the first button.
  4. Change the Content property of the new button to ‘Blue’.
  5. Image19.jpg

  6. Select the Events button of the Properties panel and type ‘Btn2_Click’ in the Click event textbox. Press Enter to open the code editor window.
  7. In the Btn2_Click event procedure, type in the following code:
  8. VB
    Dim BlueSkin as New ResourceDictionary
    BlueSkin.Source = New Uri("BlueSkin.xaml", UriKind.Relative)
    Me.Resources.MergedDictionaries.Clear()
    Me.Resources.MergedDictionaries.Add(BlueSkin)
  9. Run the project. Notice that clicking the two buttons allows you to switch between the two skins.

Saving State

The application is currently opening with the default skin, BlueSkin, when you change the skin and close the application. In order to enable the application to open with the selected skin, we shall make use of application settings.

  1. Right click the project in the Project panel, and select Edit in Visual Studio from the context menu.
  2. Once Visual Studio opens, right click the project in Solution Explorer and select Properties from the context menu. This opens the Properties window.
  3. Select the Settings tab. Create a new setting named SkinPath of type String and Scope of User. Leave the Value section blank.
  4. Double click on MainWindow.xaml.vb to open it for editing.
  5. Select ‘MainWindow Events’ from the Class Name combobox, and Loaded from the Method Name combo box.
  6. In the MainWindow_Loaded event procedure, type in the following code:
  7. VB
    'Check whether SkinPath has a value and create
    'a resource dictionary…
    If My.Settings.SkinPath <> String.Empty Then
        Dim newDictionary As New ResourceDictionary()        
        Dim path As String
        path = My.Settings.SkinPath
        newDictionary.Source = New Uri(path, UriKind.Relative)
        Me.Resources.MergedDictionaries.Clear()
        Me.Resources.MergedDictionaries.Add(newDictionary)
    End If
  8. In the Btn1_Click event procedure, add the following code:
  9. VB
    My.Settings.SkinPath = "\RedSkin.xaml"
    My.Settings.Save()
  10. In the Btn2_Click event procedure, add the following code:
  11. VB
    My.Settings.SkinPath = "\BlueSkin.xaml"
    My.Settings.Save()

    In the MainWindow_Loaded event procedure, we check whether the setting SkinPath contains a value and create a resource dictionary whose source property is assigned a URI object that has the setting as the location of a resource dictionary. In the button click event procedures, we assign the setting SkinPath with the location of the relevant resource dictionaries. We then persist the setting by calling the Save method.

  12. Run the application.
  13. Change the skin to red and close the application.
  14. Run the application again. Notice that it now opens with the last skin we had applied.

Skinning UserControls

There are several steps you can take when it comes to skinning user controls.

  1. When creating your user control, you can expose the properties of an element that make up a control so that once you place the user control on your window, you can convert that property into a resource. To do this, use dependency properties.
  2. When creating a user control, create resources from the properties of the elements that make up the control, i.e., when the user control file is open in Blend, select the elements that you want to skin and create resources from the properties of interest.

In Conclusion

I hope that the tutorial was of great help, but I couldn’t finish without taking into account the debate over whether developers should also act as designers. My thought on this is that since Blend offers one the opportunity to put on both hats, why not do so. I am of the opinion that there is a developer out there who can also be a good designer, and vice versa.

External Links

History

  • 4th May, 2010: Initial post.
  • 23rd Jan, 2011: Article text updated.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Kenya Kenya
Experienced C# software developer with a passion for WPF.

Awards,
  • CodeProject MVP 2013
  • CodeProject MVP 2012
  • CodeProject MVP 2021

Comments and Discussions

 
QuestionThanks for your article! Pin
ChinaGovermentCEO22-Nov-17 20:52
ChinaGovermentCEO22-Nov-17 20:52 
Questionvery nice Pin
BillW3314-Feb-12 5:14
professionalBillW3314-Feb-12 5:14 
GeneralRe: very nice Pin
Meshack Musundi14-Feb-12 20:22
professionalMeshack Musundi14-Feb-12 20:22 
GeneralMy vote of 5 Pin
Ahmet Yön1-Oct-11 4:55
Ahmet Yön1-Oct-11 4:55 
GeneralMany thanks Pin
iflowtech20-Apr-11 11:40
iflowtech20-Apr-11 11:40 
GeneralRe: Many thanks Pin
Meshack Musundi20-Apr-11 20:42
professionalMeshack Musundi20-Apr-11 20:42 
GeneralExcellent Pin
stoney_rocks1-Aug-10 21:31
stoney_rocks1-Aug-10 21:31 
GeneralMy feedback Pin
elisleonidus20-Jun-10 8:11
elisleonidus20-Jun-10 8:11 
GeneralRe: My feedback Pin
Meshack Musundi20-Jun-10 23:45
professionalMeshack Musundi20-Jun-10 23:45 
GeneralNice Pin
karukutimothy7-Jun-10 3:09
karukutimothy7-Jun-10 3:09 
GeneralRe: Nice Pin
Meshack Musundi8-Jun-10 22:24
professionalMeshack Musundi8-Jun-10 22:24 
GeneralSource Won't Open in Blend 3 Pin
MPoone6-May-10 5:22
MPoone6-May-10 5:22 
GeneralRe: Source Won't Open in Blend 3 Pin
Alan Beasley6-May-10 5:55
Alan Beasley6-May-10 5:55 
GeneralRe: Source Won't Open in Blend 3 Pin
Meshack Musundi6-May-10 9:23
professionalMeshack Musundi6-May-10 9:23 
GeneralNice Pin
purandareganesh6-May-10 0:13
purandareganesh6-May-10 0:13 
This is nice
GeneralRe: Nice Pin
Meshack Musundi6-May-10 4:18
professionalMeshack Musundi6-May-10 4:18 
GeneralGood reading... Pin
Stephan Johnson4-May-10 8:42
Stephan Johnson4-May-10 8:42 
GeneralRe: Good reading... Pin
Meshack Musundi4-May-10 21:01
professionalMeshack Musundi4-May-10 21:01 
GeneralRe: Good reading... Pin
TassosK5-May-10 8:36
TassosK5-May-10 8:36 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.