【问题标题】:WPF Styles based on parent styles基于父样式的 WPF 样式
【发布时间】:2020-01-29 20:49:09
【问题描述】:

假设我有一个用于容器元素的 WPF 样式,例如自动将样式应用于其子项的网格,如下所示:

<Window.Resources>
    <Style TargetType="Grid" x:Key="FormStyle">
        <Style.Resources>
            <Style TargetType="Label">
                <Setter Property="FontSize" Value="50"/>
            </Style>
        </Style.Resources>
    </Style>
</Window.Resources>

然后我怎样才能在网格本身中覆盖该样式的某些元素?例如,假设我希望一个网格有 FormStyle 但也有一个蓝色标签,就像这样(这不起作用):

<!-- this works fine and Label size = 50 -->
<Grid Style="{StaticResource FormStyle}">
    <Label Content="Blah"/>
</Grid>

<!-- But this doesnt, label is blue, but normal font size -->
<Grid Style="{StaticResource FormStyle}">
    <Grid.Resources>
        <Style TargetType="Label" BasedOn="{StaticResource {x:Type Label}}">
            <Setter Property="Foreground" Value="Blue"/>
        </Style>
    </Grid.Resources>
    <Label Content="Blah"/>
</Grid>

我希望 BasedOn={StaticResource {x:Type Label}} 引用当前范围内标签的当前活动样式 - 即 FormStyle 中的标签样式。但它显然不是,而是指基本的外部标签样式。

如果我在全球范围内这样做

<Style TargetType="Label">
    <Setter Property="FontSize" Value="50"/>
</Style>

然后就没事了。

我当然可以只命名样式,但肯定有更简单/不那么冗长的方式吗?

谢谢

【问题讨论】:

    标签: wpf xaml


    【解决方案1】:

    这里是静态资源的查找过程:

    1. 查找过程在资源中检查请求的键 由设置属性的元素定义的字典。

    2. 然后查找过程向上遍历逻辑树到 父元素及其资源字典。这个过程继续 直到到达根元素。

    3. 检查应用程序资源。应用程序资源是其中的那些资源 Application 对象定义的资源字典 为您的 WPF 应用程序。

    在您的情况下,解决BasedOn="{StaticResource {x:Type Label}}" WPF 首先查看Grid 内部定义的ResourceDictionary,然后查看Window - Grid 的逻辑父级 - 它是Resources,最后是Application级资源。 WPF 在任何地方都找不到它 - 并且默认为基本样式 - 因为该样式是 FormStyle 中的嵌套样式。

    Docs 上进一步了解静态资源查找行为。

    要获得所需的输出,您可以:

    1) 将您的 Label 样式移出 FormStyle 并移入 Window.Resoruces

    2) 将FormStyle 中的标签样式合并到Grid 元素中定义的标签样式中。

    <Grid Style="{StaticResource FormStyle}">
        <Grid.Resources>
            <Style TargetType="Label">
                <Setter Property="Foreground" Value="Red"/>
                <Setter Property="FontSize" Value="50"/>
            </Style>
        </Grid.Resources>
        <Label Content="Blah"/>
    </Grid>
    

    3) 更改您的 FormStyle,使其不具有 Label 的嵌套样式,而是具有标签属性的设置器。

    <Window.Resources>
        <Style TargetType="Grid" x:Key="FormStyle">
            <Setter Property="Label.FontSize" Value="50"/>
        </Style>
    </Window.Resources>
    

    【讨论】:

    • 非常感谢非常有帮助。移动到 Window/Grid 有点违背了这一点,因为它打算成为多个窗口/控件使用的应用程序级别样式(我没有提到有问题的)。第 3 点很棒
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-26
    • 1970-01-01
    • 2021-10-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多