89

I want to be able to define a font family for my WPF application. Preferably using a resource dictionary as a theme referenced from App.xaml. I've tried creating a Style as follows:

<Style TargetType="{x:Type Control}">
    <Setter Property="FontFamily" Value="Segoe UI" />            
</Style>

But this doesn't work. Setting the type to TextBlock works for most controls but there are a few controls where this doesn't apply.

I know you can set the font on a window and have all child controls of that window inherit the font. But I think any dialog windows will go back to the default font, which is not exactly what I want.

Any ideas?

Danny Beckett
  • 20,529
  • 24
  • 107
  • 134
RogueX
  • 1,973
  • 2
  • 15
  • 14

6 Answers6

68

Assuming your Window subclasses don't override DefaultStyleKey, you can simply add it to your Window style, since TextElement.FontFamilyProperty is an inherited property:

<Style TargetType="{x:Type Window}"> 
    <Setter Property="FontFamily" Value="Segoe UI" />             
</Style> 

You also need to add the following to your App constructor after the InitializeComponent call:

FrameworkElement.StyleProperty.OverrideMetadata(typeof(Window), new FrameworkPropertyMetadata
{
    DefaultValue = FindResource(typeof(Window))
});

How it works: After the App object finishes initializing, the Window style specified therein is made the default style for all windows.

Danny Beckett
  • 20,529
  • 24
  • 107
  • 134
Ray Burns
  • 62,163
  • 12
  • 140
  • 141
  • This does not work because the Style is not applied to types that are inherited form Window. – Matze Aug 13 '10 at 08:30
  • @Matze: It works for me. Perhaps you accidentally overrode DefaultStyleKey or explicitly set a window style? – Ray Burns Aug 13 '10 at 19:04
  • 1
    @Ray: Your snippet definitely does not work. Because you have to use a class derived from Window, some additional code and/or xal is involved. – Matze Aug 16 '10 at 14:53
  • @Matze: Try it, it works! Do this: 1. Create a new WPF Application in Visual Studio. 2. Add the code above to your Application.Resources. 3. Add a Button to Window1 with text content. 4. Run. You will see the font has changed (this is more obvious if you use Value="Times New Roman"). 5. Add window Window2 with another Button. 6. Add "new Window2().Show()" to Window1's constructor. 7. Run again. You will see that both windows pick up the new font. 8. Figure out what's different between your code and this simple example you'll know where you're going wrong. – Ray Burns Aug 18 '10 at 18:31
  • @Ray: Does not work. Just created the example as you suggested. The Style is only applied to the designer view. Maybe you something like – Matze Aug 19 '10 at 08:59
  • 1
    @Matze: This was very puzzling because what I wrote in my answer is *exactly* the code I use in my production applications. I finally figured out why it worked for me but not for you and have updated my answer to correct the problem. Thank you very much for bringing this to my attention. – Ray Burns Aug 20 '10 at 04:33
  • 2
    Or inside the protected override void OnStartup(StartupEventArgs e) of your Application class. Because you need to create your own Main method to directly call InitializeComponent of App. Thanks for your efforts to help! – Matze Aug 20 '10 at 08:50
  • Actually I don't have my own Main method. I simply do it in the App object's constructor. All I write is `public App() { InitializeComponent(); FrameworkElement.StyleProperty.OverrideMetadata(...); }`. This seems cleaner to me than putting it in OnStartup. – Ray Burns Aug 20 '10 at 09:32
  • This method is not working for me. I'm not sure why InitializeComponent() is here - the Application class doesn't have that method. In case App is supposed to be a form class, I tried that, which also didn't work – Kieren Johnstone Feb 24 '11 at 14:16
  • @Kieren: When you create a WPF project using Visual Studio it creates an App.xaml.cs and an App.xaml. The App class in App.xaml.cs is a partial class, and App.xaml adds an InitializeComponent() method to it. If your compiler is telling you your App class don't have an InitializeComponent(), check that your App.xaml has the right x:Class, including the right NET Framework namespace. If your application is structured differently, you can add this code somewhere else in your application startup. – Ray Burns Apr 01 '11 at 22:34
  • 3
    This didn't work for me. I put `Style = (Style)FindResource(typeof(Window));` right after the InitializeComponent() call instead and that worked for me. Thanks goes to http://avolk.parivedasolutions.com/2011/03/default-wpf-application-font.html – user1151923 Jan 16 '13 at 20:55
  • But it doesn't affect TextBox, so what to do about it? – henon Sep 30 '14 at 12:02
  • This is the correct solution but don't put it into the App constructor. Its place is in the App's `Startup` handler. You might also want to create additional similar styles, not just for `Window`, and call the accordingly (eg. for menus). – Gábor Jan 28 '23 at 12:53
30

Most of proposed solutions didn't work for me. My simple solution:

Add this to App.xaml:

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

Add this in your MainWindow constructor (after InitializeComponent):

Style = (Style)FindResource(typeof(Window));
Jowen
  • 5,203
  • 1
  • 43
  • 41
20

Actually you can get a full XAML solution combining some of the other answers here.

If your main window is called WinMain (the one you load before all others), just add a reference to a style named e.g. WinAll

<Window x:Class="MyNamespace.WinMain"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Title="WinMain" Height="450" Width="800"
    Style="{StaticResource WinAll}">

and then define your style this way

<Style x:Key="WinAll" TargetType="{x:Type Window}">
    <Setter Property="FontFamily"
        Value="Comic Sans MS" />
    <Setter Property="FontSize"
        Value="14" />
</Style>
Francesco B.
  • 2,729
  • 4
  • 25
  • 37
  • 3
    It may look not elegant for the first glace, it's the best way for vs2015+.net framework 4.5.2, out of every answers I found. – Val Sep 05 '19 at 03:47
  • 1
    I find this to be the most elegant version. When using the hot reload feature if the answer from Jowen is used it can't be hot reloaded. However with this answer it is easily possible to hot reload since it just is treated as a normal style. – darophi Nov 23 '19 at 09:45
  • 1
    This is exactly what I was looking for. Thanks! – Louis van Tonder Feb 26 '21 at 08:52
  • 2
    Beautiful, the Style just needs to be in App.xaml. – Martin Braun Oct 31 '21 at 23:08
17

One simple way to do it programmatically:

public MainWindow()
{
    this.FontFamily = new FontFamily("Segoe UI");
}
Strong84
  • 1,869
  • 2
  • 19
  • 24
  • This one worked for me, with XAML from Rays answer (to get both editor view and runtime font correct) – mgear Mar 20 '20 at 11:17
10

I found this :

TextElement.FontFamilyProperty.OverrideMetadata(
typeof(TextElement),
new FrameworkPropertyMetadata(
    new FontFamily("Comic Sans MS")));

TextBlock.FontFamilyProperty.OverrideMetadata(
typeof(TextBlock),
new FrameworkPropertyMetadata(
    new FontFamily("Comic Sans MS")));
Ehsan Zargar Ershadi
  • 24,115
  • 17
  • 65
  • 95
0

Try this simple workaround in the App.xaml (no code behind needed):

<SolidColorBrush x:Key="ForeBrush" Color="Blue" />

<Style x:Key="GenericTextStyle">
    <!-- Generic control forecolor definition -->
    <Setter Property="Control.Foreground" Value="{StaticResource ForeBrush}" />

    <!-- Add a definition for each unworking nested control -->
    <Style.Resources>
        <Style TargetType="{x:Type Label}">
            <Setter Property="Foreground" Value="{StaticResource ForeBrush}" />
        </Style>
    </Style.Resources>
</Style>

Just bind your windows style to this. Works perfectly for me. Only some properties need to be defined in the nested tree. For example the property FontSize can be specify only in the generic section.

I don't know why is necessary to do this trick. It's strange because Label should be derived from Control. Anyone have any idea about it?

Diosney
  • 10,520
  • 15
  • 66
  • 111
LoxLox
  • 977
  • 9
  • 16