Click here to Skip to main content
Click here to Skip to main content

Skinning a WPF App in Blend

By , 23 Jan 2011
Rate this:
Please Sign up or sign in to vote.

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. 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:

     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. 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. '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. My.Settings.SkinPath = "\RedSkin.xaml"
    My.Settings.Save()
  10. In the Btn2_Click event procedure, add the following code:
  11. 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)

About the Author

Meshack Musundi
Software Developer
Kenya Kenya
Meshack is an avid programmer with a bias towards WPF and VB.NET. He has about 5 years of programming experience initially starting off with Java before shifting to .NET, thanks to the allure of WPF. He has developed several applications, and written several articles about them, which can be viewed here on CodeProject. He currently resides in a small town in Kiambu county, Kenya.
 
Awards;
  • CodeProject MVP 2013
  • CodeProject MVP 2012
  • Best VB.NET article of August 2013
  • Best VB.NET article of February 2013
  • Best VB.NET article of October 2012
  • Best VB.NET article of July 2012
  • Best VB.NET article of February 2012
  • Best VB.NET article of January 2012
  • Best VB.NET article of November 2011
  • Best VB.NET article of June 2011
  • Best VB.NET article of May 2011
  • Best VB.NET article of March 2011
  • Best VB.NET article of February 2011
  • Best VB.NET article of January 2011
  • Best VB.NET article of December 2010
  • Best VB.NET article of November 2010

Comments and Discussions

 
Questionvery nice PinmemberCIDev14-Feb-12 5:14 
GeneralRe: very nice PinmvpMeshack Musundi14-Feb-12 20:22 
GeneralMy vote of 5 PinmemberAhmet Yön1-Oct-11 4:55 
GeneralMany thanks Pinmemberiflowtech20-Apr-11 11:40 
GeneralRe: Many thanks PinmemberMeshack Musundi20-Apr-11 20:42 
GeneralExcellent Pinmemberstoney_rocks1-Aug-10 21:31 
GeneralMy feedback Pinmemberelisleonidus20-Jun-10 8:11 
GeneralRe: My feedback PinmemberMeshack Musundi20-Jun-10 23:45 
GeneralNice Pinmemberkarukutimothy7-Jun-10 3:09 
GeneralRe: Nice PinmemberMeshack Musundi8-Jun-10 22:24 
GeneralSource Won't Open in Blend 3 PinmemberMOverstreet6-May-10 5:22 
GeneralRe: Source Won't Open in Blend 3 PinmemberAlan Beasley6-May-10 5:55 
GeneralRe: Source Won't Open in Blend 3 PinmemberMeshack Musundi6-May-10 9:23 
GeneralNice Pinmemberpurandareganesh6-May-10 0:13 
GeneralRe: Nice PinmemberMeshack Musundi6-May-10 4:18 
GeneralGood reading... PinmemberStephan Johnson4-May-10 8:42 
GeneralRe: Good reading... PinmemberMeshack Musundi4-May-10 21:01 
GeneralRe: Good reading... PinmemberTassosK5-May-10 8:36 

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

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

| Advertise | Privacy | Mobile
Web01 | 2.8.140421.2 | Last Updated 23 Jan 2011
Article Copyright 2010 by Meshack Musundi
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid