locked
question about tying into windows themes vs. Skinning RRS feed

  • Question

  • I have tied my windows in to the windows theme engine by doing things like assigning my windows backgrounds to WindowsBrushKey and WindowTextBrushKey.  This works great--when I alter my theme to high contrast, for example, my windows dynamically follow suit.  Where I am confused is overriding that theme with a skin.  I would like to allow the user to override the default theme look and feel of my application in favour of a skin that would replace the templates with skinned elements...  I've read that this is done by having multiple dispirately named resource dictionaries, but you keep the name of the resources inside identical between the different resource dictionaries.  That way, you can swap one dictionary for another, and the entire look of the application changes.

    What is the practice for overriding the windowsBrushKeys so that a skin can take over...but when the skin isn't active, the brushes etc are still tied in to the windows theme colour scheme engine?


    Purkiss
    Monday, January 11, 2010 6:50 PM

Answers

  • Allow me to answer my own question for the benefit of future WPF'ers.

    Creating a windows-controlled theme
    I have created a folder called Themes in my project
    In this folder I currently have one folder, Generic.  In the generic folder, I have all the resource dictionary files I want used to theme my application:

    Generic.xaml (the main resource dictionary file which has merge entries for the following)
    GenericBrushesAndColours.xaml 
    GenericButtons.xaml
    GenericArtwork.xaml
    GenericDataTemplates.xaml

    I have several resource dictionaries to categorize my resources and make it easy to navigate...but you could put EVERYTHING in one resource dictionary if you really wanted to.  Ensure that dependencies go first (ie, brushes and colours are declared prior to being used in artwork or buttons, whatever).

    In Generic, I do not override any of the windows styles.  If I create a style template for another theme (for example, a login button), but want it to be generic in my generic theme, I set the style of the button to dead end in my resource dictionary:

    <Style x:Key="LoginButton" TargetType="{xType Button}"/>

    This tells WPF to check my resource dictionary for the LoginButton style...but since I don't want one applied, it just dead ends and uses the default Type style (in this case, a button, controlled by the windows theme engine).

    Creating a Skin that can be used to override the windows theme

    Now to create a skin that can be used to override the generic theme I created, I create a Skins folder in my wpf project.

    In the skins folder, I create a folder for my skin...let's call it Nintendo.

    In the Nintendo folder, I create the SAME number, type and content of resource dictionaries as I created for Generic:

    Nintendo.xaml (the main resource dictionary file which has merge entries for the following)
    NintendoBrushesAndColours.xaml 
    NintendoButtons.xaml
    NintendoArtwork.xaml
    NintendoDataTemplates.xaml

    It is important that you replicate EVERY style used and referenced across all your themes and skins.

    As a result, since I had a LoginButton style specified in my project (which dead-ends in GenericButtons.xaml)...I MUST have a style in my Nintendo skin...even if I choose to dead end it.  However, in this case, I may want a nintendo style button:

    <Style x:Key={LoginButton} TargetType="{x:Type Button}">
    <Setter Property ="Template">
    <ControlTemplate TargetType={x:Type Button}">
    <ControlTemplate.Resources>
    .... ETC
    </Style>

    How do I switch between the theme and the skin?

    Identify app.xaml and have one theme or skin referenced at a time only in the resources area:

    <Application.Resources>
    		<ResourceDictionary>
    			<ResourceDictionary.MergedDictionaries>				
                    
    				<!-- THEME OR SKIN SELECTION-->
    				<!-- ONE must be enabled -->
    				
    				<!-- GENERIC, WINDOWS THEME ENGINE ENABLED -->
    				<ResourceDictionary Source="Themes/Generic/Generic.xaml"/>
    				
    				<!-- Nintendo Skin -->
    				<!--ResourceDictionary Source="Skins/Nintendo/Nintendo.xaml"/-->
    				
    			
    			</ResourceDictionary.MergedDictionaries>			
    		</ResourceDictionary>
    	</Application.Resources>


    This is at design time and running for testing purposes.  To allow the user to change the theme or skin at runtime, check out this blog:


    Purkiss
    • Marked as answer by Purkiss Thursday, February 18, 2010 4:33 PM
    Thursday, February 18, 2010 4:33 PM