locked
Overriding ResourceDictionary values

    Question

  • I can't find an answer to a very simple and basic question. I have a control library that has a default set of themes defined exactly like the generic.xml example.

    Teraque.PresentationFramework/Themes/generic.xaml:

    <ResourceDictionary xmlns:controls="using:Teraque.UI.Xaml.Controls" xmlns:local="using:Teraque.UI.Xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <ResourceDictionary.ThemeDictionaries> <ResourceDictionary x:Key="Default"> <x:Double x:Key="ColumnFontSize">8</x:Double> </ResourceDictionary> <ResourceDictionary x:Key="Light"> <x:Double x:Key="ColumnFontSize">8</x:Double> </ResourceDictionary> <ResourceDictionary x:Key="Dark"> <x:Double x:Key="ColumnFontSize">8</x:Double> </ResourceDictionary> </ResourceDictionary.ThemeDictionaries> <!-- DataMatrix Cell Style --> <Style TargetType="controls:DataMatrixCell"> <Setter Property="FontSize" Value="{ThemeResource ColumnFontSize}"/> <Setter Property="HorizontalContentAlignment" Value="Left"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="controls:DataMatrixCell"> <Border Padding="{TemplateBinding Padding}"> <ContentPresenter/> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style>

    Now in my application, I want to override the 'ColumnFontSize', so I use this:

    App.xaml

    <Application x:Class="Teraque.Sandbox.App"
                 RequestedTheme="Light"
    			 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    			 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
        <Application.Resources>
            <ResourceDictionary>
                <ResourceDictionary.ThemeDictionaries>
                    <ResourceDictionary x:Key="Light">
                        <x:Double x:Key="ColumnFontSize">50.0</x:Double>
                    </ResourceDictionary>
                </ResourceDictionary.ThemeDictionaries>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="ms-appx:///Teraque.PresentationFramework/Themes/generic.xaml"/>
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
        </Application.Resources>
    </Application>
    The values are not overridden.  The column font size in my control is still the 8 point font declared in the original generic.xaml.  Nothing I've tried allows me to override the value.  I've tried placing the override after the merge dictionary, I've tried placing the values in their own merged library.  How are we supposed to expand on the views of controls provided in base libraries?


    • Edited by DRAirey1 Sunday, November 16, 2014 10:15 PM
    Sunday, November 16, 2014 12:43 AM

Answers

  • Got it.

    <Application x:Class="Teraque.Sandbox.App"
                 RequestedTheme="Light"
    			 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    			 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
        <Application.Resources>
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="ms-appx:///Teraque.PresentationFramework/Themes/generic.xaml">
                        <ResourceDictionary.ThemeDictionaries>
                            <ResourceDictionary x:Key="Light">
                                <x:Double x:Key="ColumnFontSize">50</x:Double>
                            </ResourceDictionary>
                        </ResourceDictionary.ThemeDictionaries>
                    </ResourceDictionary>
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
        </Application.Resources>
    </Application>
    

    • Marked as answer by DRAirey1 Monday, November 17, 2014 11:42 AM
    Monday, November 17, 2014 2:03 AM

All replies

  • You could add the style that you want to override the one defined in the class library to a resource dictionary in the App project and then add this resource dictionary to App.xaml after the other one:

    Generic2.xaml:

    <ResourceDictionary
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:App8.Themes">
        <ResourceDictionary.ThemeDictionaries>
            <ResourceDictionary x:Key="Default">
                <x:Double x:Key="ColumnFontSize">50</x:Double>
            </ResourceDictionary>
            <ResourceDictionary x:Key="Light">
                <x:Double x:Key="ColumnFontSize">50</x:Double>
            </ResourceDictionary>
            <ResourceDictionary x:Key="Dark">
                <x:Double x:Key="ColumnFontSize">50</x:Double>
            </ResourceDictionary>
        </ResourceDictionary.ThemeDictionaries>
    </ResourceDictionary>


    App.xaml:

    <Application.Resources>
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="ms-appx:///Teraque.PresentationFramework/Themes/generic.xaml"/>
                    <ResourceDictionary Source="Themes/generic2.xaml"/>
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
        </Application.Resources>
    Please remember to mark helpful posts as answer and/or helpful.


    Sunday, November 16, 2014 9:28 PM
  • Have you actually tried that solution?  It was one of the earliest ones that I tried and I was unable to get the application's 'generic2.xaml' theme to override the resource dictionary values in the 'generic.xaml' library.  If you have a working example, I'd love to see it.

    The strange thing is we can override the system defined resources for the system controls (ListView, GridView, etc.), but not ones that we define in our own shared controls library.

    • Edited by DRAirey1 Sunday, November 16, 2014 9:45 PM
    Sunday, November 16, 2014 9:44 PM
  • MainPage.xaml:

    <StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
            <TextBlock FontSize="{ThemeResource ColumnFontSize}">Test...</TextBlock>
            
            <Button Style="{StaticResource testStyle}">Test</Button>
        </StackPanel>


    Generic2.xaml:

    <ResourceDictionary
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:App9">
        <ResourceDictionary.ThemeDictionaries>
            <ResourceDictionary x:Key="Default">
                <x:Double x:Key="ColumnFontSize">50</x:Double>
            </ResourceDictionary>
            <ResourceDictionary x:Key="Light">
                <x:Double x:Key="ColumnFontSize">50</x:Double>
            </ResourceDictionary>
            <ResourceDictionary x:Key="Dark">
                <x:Double x:Key="ColumnFontSize">50</x:Double>
            </ResourceDictionary>
        </ResourceDictionary.ThemeDictionaries>
    </ResourceDictionary>


    ClassLibrary1 Themes/Generic.xaml:

    <ResourceDictionary
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:ClassLibrary1.Themes">
        <ResourceDictionary.ThemeDictionaries>
            <ResourceDictionary x:Key="Default">
                <x:Double x:Key="ColumnFontSize">8</x:Double>
            </ResourceDictionary>
            <ResourceDictionary x:Key="Light">
                <x:Double x:Key="ColumnFontSize">8</x:Double>
            </ResourceDictionary>
            <ResourceDictionary x:Key="Dark">
                <x:Double x:Key="ColumnFontSize">8</x:Double>
            </ResourceDictionary>
        </ResourceDictionary.ThemeDictionaries>
        <Style x:Key="testStyle" TargetType="Button">
            <Setter Property="FontSize" Value="{ThemeResource ColumnFontSize}"/>
        </Style>
    </ResourceDictionary>


    Note that you cannot override the ThemeResource that is applied to the FontSize property of the Button that is defined in the class library in the above example though if that's what you are trying to do. This is not possible due to the way theme resources are looked up, i.e the style in the class library cannot get the value of the "overriding" theme resource in the App.

    However, the TextBlock in MainPage.xaml will get the overridden font size value.

    Please remember to mark helpful posts as answer and/or helpful.

    Sunday, November 16, 2014 10:27 PM
  • Magnus, I'm very confused now.  I can accept that a static resource might be fixed to only what the shared library knows (that is, it only knows about the 'ColunFontSize' declared in the libraries xaml).  But I thought the 'ThemeResource' was supposed to be something calculated at runtime.  How come, at runtime, the shared library can't follow the visual tree up to the application and find the resources there?

    This certainly makes the job of creating shared views and controls much more difficult as the theme is fixed at the library level and can't use a theme described at the application level.  Your explanation, while empirically correct, seems to fly in the face of the stated goals of the ResourceDictionary.



    • Edited by DRAirey1 Sunday, November 16, 2014 11:34 PM
    Sunday, November 16, 2014 11:03 PM
  • Got it.

    <Application x:Class="Teraque.Sandbox.App"
                 RequestedTheme="Light"
    			 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    			 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
        <Application.Resources>
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="ms-appx:///Teraque.PresentationFramework/Themes/generic.xaml">
                        <ResourceDictionary.ThemeDictionaries>
                            <ResourceDictionary x:Key="Light">
                                <x:Double x:Key="ColumnFontSize">50</x:Double>
                            </ResourceDictionary>
                        </ResourceDictionary.ThemeDictionaries>
                    </ResourceDictionary>
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
        </Application.Resources>
    </Application>
    

    • Marked as answer by DRAirey1 Monday, November 17, 2014 11:42 AM
    Monday, November 17, 2014 2:03 AM