Wpf – (WPF) How to set value of a sys:Double to SystemFonts.MessageFontSize from ResourceDictionary

dynamicresourcefont-sizeresourcedictionarywpf

Scenario:

I want to use 3 standard font size for my WPF application : BigFontSize, NormalFontSize, and SmallFontSize. These are double values and they are defined in resource dictionary as (where sys is appropriately defined):

<sys:Double x:Key="BigFontSize">18</sys:Double>
<sys:Double x:Key="NormalFontSize">14</sys:Double>
<sys:Double x:Key="SmallFontSize">12</sys:Double>

This works well. But i have randomly selected 14 as a normal size. What i want is to get a system defined font size for NormalFontSize. (If that's done, I can use a converter as described here to get BigFontSize and SmallFontSize relative to NormalFontSize)

Clue :

I found from the documentation that default font size is stored in a static property (double) SystemFonts.MessageFontSize. But what should I do to retrieve that value to resource dictionary? (I know Binding or DynamicResource cannot be applied. But hey, this is a static value, so how can I apply StaticResource or x:Static or whatever?)

I have tried

<sys:Double x:Key="XXXFontSize">
    <StaticResource ResourceKey="SystemFonts.MessageFontSize" />
</sys:Double>

and

<sys:Double x:Key="XXXFontSize">
    <x:Static ResourceKey="SystemFonts.MessageFontSize" />
</sys:Double>

Both of which doesn't seem to work (as expected). I get an error saying Cannot add content to object of type 'System.Double'.

Note:

  • I don't want to do this from code, e.g from App(). (Is it possible to have a code-behind for ResourceDictionary?)
  • I don't want to encapsulate this in generalized style from which other styles can be derived (using BasedOn) because I have several Resource Dictionaries, and it'll not be possible to use DynamicResource with BasedOn
    That is, I cannot use

    <Style x:Key="BigFont" TargetType="{x:Type Control}"}>
        <Setter Property="Control.FontSize" 
                Value="{Binding Source={x:Static SystemFonts.MessageFontSize},
                                Converter={ . . . }" />
    </Style>
    

    Because, if I have a style in other ResourceDictionary, say HeaderTextBlockStyle, then I would have to use BasedOn={DynamicResource BigFont} which is not possible (I think)

Any help would be greatly appreciated.
Thank you.

TAGS : WPF SystemFonts.MessageFontSize ResourceDictionary FontSize BasedOn DynamicResource

Best Answer

I've done like this...

public partial class GlobalResources : ResourceDictionary
{
    public GlobalResources()
    {
        this.Add("GiantFontSize", SystemFonts.MessageFontSize * 2.5);
        this.Add("BigFontSize", SystemFonts.MessageFontSize * 1.5);
        this.Add("MediumFontSize", SystemFonts.MessageFontSize * 1.25);
        this.Add("NormalFontSize", SystemFonts.MessageFontSize);
        this.Add("SmallFontSize", SystemFonts.MessageFontSize * 0.85);
    }
}

... and it's working like like a miracle!!! I can use these resources in the same (partial) resource dictionary or from other resource dictionaries like this...

<Style ...>
    <Setter Property="FontSize"
            Value="{DynamicResource MediumFontSize}" />

    ...

</Style>

I don't know if it is a "good practice" or not (please comment on this), I only know that it works..!!!

Related Topic