WPF全局字体大小

88
我正在创建一个WPF应用程序,想知道如何以最佳方式更改UI中每个元素的字体大小。 我需要创建资源字典并设置样式来设置所有使用的控件的字体大小吗?什么是最佳实践?
11个回答

111

我会这样做:

<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>

这样,如果我想更改所有控件,我只需要更改“baseStyle”样式,其余控件将从它继承。(这就是BasedOn属性所做的事情,如果在继承样式中创建其他Setter,则还可以扩展基本样式)


3
如果需要动态更改字体大小,请确保在样式和对“baseStyle”进行引用的样式中,所有字体大小都声明为DynamicResource。请注意,修改内容时不要改变原意,并使其更加通俗易懂。 - Jeff Wain
1
忘记了那个小问题。我们已经将所有的声明都设置为每个控件声明一个Setter,这样我们就不会有巨大的层级结构。这篇帖子解释得很好。 https://dev59.com/SnRB5IYBdhLWcg3wkH9N - Jeff Wain
@Ian Boyd:你是什么意思?请再详细解释一下。 - Carlo
2
@Ian Boyd:但那个人只想要改变他所有控件的字体大小,而不是控件本身的大小。你所谈论的是完全不同的问题。 - Carlo
样式的TargetType和其BasedOn样式的TargetType应该相同!因此,您的示例XAML将产生InvalidOperationException异常。例如,当声明一个TargetType为TextBlock的样式,并使用BasedOn指向一个TargetType为Control的样式时,结果错误将是:InvalidOperationException:只能基于目标类型为“TextBlock”的基类型样式。 - Amir Mahdi Nassiri
显示剩余5条评论

50
< p >FontSizeProperty 继承自父控件。因此,您只需更改主窗口的字体大小即可。

如果您不需要动态行为,则应该可行:

向ResourceDictionary添加一个Window样式。

<Style TargetType="{x:Type Window}">
     <Setter Property="FontSize" Value="15" />
</Style>
将样式应用于您的主表单(不会隐式应用,因为它是派生类型)。
 Style = (Style)FindResource(typeof (Window));

这似乎比被标记为解决方案的答案更好的实践。我会选择这个,无论如何它都要少得多代码。 - Koert van Kleef
2
编辑:无法工作(在任何情况下都是使用框架4.5)。 - Koert van Kleef
@KoertvanKleef - 在我的.NET 4.5上工作良好,您遇到了什么问题? - joshcomley
5
为什么要为单个元素创建样式?而不直接在元素上使用<Window FontSize="15">呢? - mins
这比已接受的解决方案要干净简单得多。 - Jeremy Morren
<Style x:Key="defaultStyles">... and <Window Style="{StaticResource defaultStyles}"></Window> just to keep it in the xaml files. - Get Off My Lawn

47
< p > <Window>有一个属性FontSize。

因此,如果您想在窗口内所有元素中更改字体大小,可以在< code > Window 元素中设置所需的字体大小。

<Window FontSize="12">

</Window>

将其应用到 Window 上通过 Setter 没有成功(虽然在设计视图中看起来像是成功了...),但这种方法成功了,而且是一个非常简单的解决方案。 - Jonas
太好了!它在大约95%的应用程序中都能正常工作。(不包括功能区按钮和可能的一些其他控件) - Yonatan Tuchinsky
当它不起作用时,很可能是因为具有更高优先级的提供程序确定了依赖属性值(例如,操作系统主题的提供程序,在此优先级列表中排名第9,而继承仅排名第10)。 - mins

34

另一种选择是将FontFamily和FontSize定义为资源。

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

这样你就可以在setter方法中使用它们。


这对我来说是最好的选择,因为它允许您在运行时使用{DynamicResource}并更改字体大小。 - Peter
7
必须导入 _xmlns:sys="clr-namespace:System;assembly=mscorlib"_,这个方法就完美地起作用了。 - dynamiclynk

12
Application.Current.MainWindow.FontSize = _appBodyFontSize;

通过这种方式,您可以在运行时更改字体大小。


7

TextElement.FontSize是一个继承属性,这意味着您可以在根元素上简单地设置字体大小,所有子元素将使用该大小(只要您不手动更改它们)。


重要提示:“只要您不手动更改它们”。我花了一些时间才弄清楚字体继承确实有效,因为我在某个父级别上手动设置了它。 - Peter Huber
这应该是被选中的答案。@PeterHuber:依赖属性的目的是依赖于多个值提供者,这些提供者具有一些预定的优先级。设置本地值具有最高优先级(除了动画和强制之外,优先级规则)。 - mins

6

对于WPF中的任何样式,您都应该有一个单独的资源字典,其中包含您应用程序的样式。

如果您想要在整个应用程序中重复使用单个字体大小,则只需为该字体大小创建样式。您可以为其指定唯一的名称/键来显式使用,也可以设置一个目标类型,该类型将贯穿整个应用程序。

显式键:

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

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

*请注意,此样式可用于具有内容呈现器的控件

对于应用程序中的所有文本块:

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

<TextBlock
        Text="This text will be size 10" />

1
如果您想在整个应用程序中重复使用单个字体大小,则只需创建样式即可。这与依赖属性 FontSizeProperty 的目的相矛盾。根据原则,依赖属性可以继承于逻辑树,因此,除非有特定的需要(例如仅在中间节点上具有不同的字体大小),否则在根元素上设置字体大小就足够了。更新该值将触发所有子级的更新。 - mins

3
如果您需要以编程方式更改全局FontSize(而不是静态的XAML),以便应用于所有窗口,您可以执行以下操作:
TextElement.FontSizeProperty.OverrideMetadata(
            typeof(TextElement),
            new FrameworkPropertyMetadata(16.0));

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

这些值适用于任何TextBlock、Labels和几乎所有窗口中的文本,只要没有明确定义FontSize。但这不适用于TextBox,您必须为其编写类似的代码或任何其他特殊控件。

这比在TextBlock元素上使用<Style>要好得多,因为否则你将不得不在每个覆盖它的地方使用BasedOn - bytecode77

2

使用Ctrl + 鼠标滚轮全局动态更改字体大小:

XAML:

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

代码后台:

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;
    }
}

this.FontSize++; - Vitalij Roscinski

2
使用XAML中的资源是最好的方法。虽然有很多很好的答案来回答这个问题,但我想要在资源的范围方面加入我的两分钱。
为了在项目的所有Windows和User Control中实现全局可访问性,您可以将资源放在App.xaml文件中。
<Application.Resources>
    <Style TargetType="{x:Type Control}" x:Key="GlobalFontSize">
        <Setter Property="FontSize" Value="28"/>
    </Style>
</Application.Resources>

为了在窗口级别上实现无障碍性,您可以在 XAML 文件中为 Window 定义资源。

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

你甚至可以将其放在控件级别,例如:
<DockPanel.Resources>
    <Style TargetType="{x:Type Control}" x:Key="GlobalFontSize">
        <Setter Property="FontSize" Value="28"/>
    </Style>
</DockPanel.Resources>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接