WPF global font size
Asked Answered
E

11

90

I'm creating a WPF app and I would like to know the best way to be able to change the font size for every element in the ui. Do I create a resource dictionary and set Styles to set the font size for all the controls I use?

What is the best practice?

Electrician answered 21/5, 2009 at 15:7 Comment(0)
W
112

I'd do it this way:

<Window.Resources>
        <Style TargetType="{x:Type Control}" x:Key="baseStyle">
            <Setter Property="FontSize" Value="100" />
        </Style>
        <Style TargetType="{x:Type Button}" BasedOn="{StaticResource baseStyle}"></Style>
        <Style TargetType="{x:Type Label}" BasedOn="{StaticResource baseStyle}"></Style>
        <Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource baseStyle}"></Style>
        <Style TargetType="{x:Type ListView}" BasedOn="{StaticResource baseStyle}"></Style>
        <!-- ComboBox, RadioButton, CheckBox, etc... -->
    </Window.Resources>

That way, if I want to change ALL the controls, I'd just have to change the "baseStyle" style, the rest would just inherit from it. (That's what BasedOn property those, you can also extend the base style if you create other setters inside of the inherited style)

Wade answered 21/5, 2009 at 17:57 Comment(10)
And if you need to change the font size on the fly, make sure that all of them are declared to DynamicResource, both in the Styles and in the Style references to "baseStyle".Stonewall
Seroiouslly? I tried doing that and I get this error: Property 'BaseOn' does not support values of type 'DynamicResourceExtension'. I just changed the code from StaticResource to DynamicResource. What do you think is missing?Wade
Forgot about that little issue. We have all our declarations set up as Setters declared per-control so that we don't have huge hierarchies. This post explains it pretty well. #585929Stonewall
I got a little curious about this issue and I went ahead to do some tests, but it seems like once you've set and are using a StaticResource, you can't modify it. Maybe a different solution is needed if you want to change the size at some point in your app.Wade
i don't think simply changing the font (face/size) of an item will change its size.Bobbe
@Ian Boyd: What do you mean? Please elaborate a bit more.Wade
@Wade Imagine the form is designed with Tahoma 8pt (i.e. Windows XP). Someone runs it on Vista (default font Segoe UI 9pt). If i set the form to Segoe UI 9pt, i don't believe elements will get 16% larger. If running on a computer set to Georgia 14pt, i don't think elements will be 127% larger. Content may expand to fit, but that doesn't solve the problem of items (i.e. buttons) that were all hard-coded to 75 logical pixels wide by 23 logical pixels high.Bobbe
@Ian Boyd: But the guy just want to change the font size in all his controls, not the size of the controls. What you're talking about is a whole different issue.Wade
An style's TargetType & its BasedOn style's TargetType SHOULD be the same! So your sample XAML will produce InvalidOperationException. For example when declaring a style with TargetType of TextBlock and using BasedOn pointing to a style with TargetType of Control, the result error will be: InvalidOperationException: Can only base on a Style with target type that is base type 'TextBlock'Sonny
The inheritance doesn't follow down both logical and visual trees, does it? this is not a full answer if that is the case.Gottfried
R
52

FontSizeProperty is inherited from Parent Control. So you just need to change FontSize of your main window.

If you don't need dynamic behaviour this should work:

Add a style for Window to your ResourceDictionary

<Style TargetType="{x:Type Window}">
     <Setter Property="FontSize" Value="15" />
</Style>

Apply the style to your main form (will not be applied implicit because its a derived type)

 Style = (Style)FindResource(typeof (Window));
Ringleader answered 13/8, 2010 at 9:2 Comment(6)
This sounds like better practice than the answer that was marked as the solution. I'll go with this, in any case it is a lot less code.Farinose
EDIT: Doesn't work (with framework 4.5 in any case).Farinose
@KoertvanKleef - it works for me on .NET 4.5, what issue are you seeing?Gardant
Why create a style for a single element? Why not just <Window FontSize="15"> directly on the element?Egyptology
This is much cleaner and simpler than the accepted solution.Hols
<Style x:Key="defaultStyles">... and <Window Style="{StaticResource defaultStyles}"></Window> just to keep it in the xaml files.Falco
E
51

<Window> has a property FontSize.

So you can set desired fontsize in element if you want to change the fontsize in all the elements within that window.

<Window FontSize="12">

</Window>
Erastian answered 6/6, 2014 at 11:44 Comment(3)
Applying it to Window via a Setter didn't work (it looked like it did in the designer view though...) but this one did and is a ridiculously simple solution to the problem.Trisomic
Its Great! it works in about 95% of the app. (excluding ribbon buttons and maybe some few other controls)Unofficial
@YonatanTuchinsky: When it doesn't work, it's probably because a provider with a higher priority determines the dependency property value (e.g. the provider for OS theme, #9 in this list of precedence while inheritance is only number #10).Egyptology
P
35

Another option is to define the FontFamily and FontSize as resources.

<FontFamily x:Key="BaseFontFamily">Calibri</FontFamily>
<sys:Double x:Key="BaseFontSize">12</sys:Double>

That way you can use them in your setters.

Prognostication answered 4/12, 2010 at 13:41 Comment(2)
This works best for me as it allows you to use {DynamicResource } and change the font sizes at runtime.Hatchel
Had to import xmlns:sys="clr-namespace:System;assembly=mscorlib" and this method worked perfect.Glasser
C
12
Application.Current.MainWindow.FontSize = _appBodyFontSize;

This way you can change the Font Size at run time also.

Chaechaeronea answered 21/5, 2011 at 13:42 Comment(0)
O
7

For any styles in WPF, you should have a separate resource dictionary that contains the styles for your app.

If you want to have a single Font Size that's reused throughout the app then just create a style for that font size. You can either give it a unique name/key to use explicitly or you can set a targetType that will transcend throughout the app.

Explicit Key:

<Style
    x:Key="MyFontSize"
    TargetType="TextBlock">
    <Setter
        Property="FontSize"
        Value="10" />
</Style>

<Control
    Style="{StaticResource MyFontSize}" />

*Note this style can be used with controls that have contentPresenters

For all textblocks in the app:

<Style
    TargetType="TextBlock">
    <Setter
        Property="FontSize"
        Value="10" />
</Style>

<TextBlock
        Text="This text will be size 10" />
Ondrej answered 21/5, 2009 at 17:6 Comment(1)
"If you want to have a single Font Size that's reused throughout the app then just create a style": this is in contradiction with the purpose of dependency property FontSizeProperty. Dependency properties are inheritable by principle in the logical tree, so unless there is a specific need (e.g. having a different font size on an intermediary node only), setting the font size on the root element is enough. Updating the value will trigger an update on all children.Egyptology
S
7

TextElement.FontSize is an inherit property, which means you can simply set the font size at root element, and all the children elements will use that size (as long as you don't change them manually)

Stag answered 16/7, 2011 at 10:6 Comment(2)
Important: "as long as you don't change them manually". It took me some time to figure out that the font inheritance did work because I set it somewhere for a parent manually.Golding
This should be the selected answer. @PeterHuber: Dependency properties are meant to be dependent on multiple value providers which have some predetermined priorities. Setting a local value has the highest priority (except animation and coercion, precedence rules).Egyptology
I
4

If you need to programmatically change global FontSize, not statically (XAML), to be applied once for all your windows, you can do:

TextElement.FontSizeProperty.OverrideMetadata(
            typeof(TextElement),
            new FrameworkPropertyMetadata(16.0));

        TextBlock.FontSizeProperty.OverrideMetadata(
            typeof(TextBlock),
            new FrameworkPropertyMetadata(16.0));

This values are applied to any TextBlock, Labels and almost any text in any windows, whereas it has not a explicit FontSize defined. But this does not affect for TextBox, you have to write a similar code for it or any other special controls.

Intermediate answered 10/11, 2010 at 16:19 Comment(1)
This is much better than a <Style> on the TextBlock element, because you would otherwise have to use BasedOn everywhere you override it!Assumed
M
3

To dynamically change the font size globally with ctrl-mousewheel:

XAML:

<Window Name="MainWindow" ... PreviewMouseWheel="MainWindow_PreviewMouseWheel">

code behind:

private void MainWindow_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
    if ((Keyboard.Modifiers & ModifierKeys.Control) != 0)
    {
        if (e.Delta > 0)
            ++mainCtrl.FontSize;
        if (e.Delta < 0 && mainCtrl.FontSize > 1)
             --mainCtrl.FontSize;
    }
}
May answered 5/11, 2018 at 13:50 Comment(0)
T
2

Using Resources in XAML is the way to go. Although there are many great answers to this question, I would like to add my two cents to the SCOPE of the Resource.

For Global accessibility in all of the Windows and User Controls of the Project, you can have your resource in the App.xaml file

<Application.Resources>
    <Style TargetType="{x:Type Control}" x:Key="GlobalFontSize">
        <Setter Property="FontSize" Value="28"/>
    </Style>
</Application.Resources>

For accessibility at a Window level, you can have your resource in your xaml file for Window

<Window.Resources>
    <Style TargetType="{x:Type Control}" x:Key="GlobalFontSize">
        <Setter Property="FontSize" Value="28"/>
    </Style>
</Window.Resources>

You could even have it at a Control level, for example

<DockPanel.Resources>
    <Style TargetType="{x:Type Control}" x:Key="GlobalFontSize">
        <Setter Property="FontSize" Value="28"/>
    </Style>
</DockPanel.Resources>
Ted answered 12/10, 2020 at 9:59 Comment(0)
H
2

Let's have some BLACK MAGIC things:

  1. Add a double resource into your Application resource
<Application.Resources>
    <sys:Double xmlns:sys="clr-namespace:System;assembly=mscorlib" x:Key="GlobalFontSize">12</sys:Double>
</Application.Resources>
  1. Add a static property in your App class
public static double GlobalFontSize
{
    get => (double)Current.Resources["GlobalFontSize"];
    set => Current.Resources["GlobalFontSize"] = value;
}
  1. Use this resource any where you want by DynamicResource
FontSize="{DynamicResource GlobalFontSize}"
  1. Access property App.GlobalFontSize in any way to change value, binding is okay!
App.GlobalFontSize = 20;
//Or
{Binding Path=(local:App.GlobalFontSize)}
Hewet answered 8/1, 2021 at 9:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.