【问题标题】:Inheriting from Application Styles (WPF)从应用程序样式继承 (WPF)
【发布时间】:2010-11-09 00:26:58
【问题描述】:

我试图在我的 WPF 应用程序中为某个 Window 继承应用程序级样式,但我无法让它继承而不是简单地覆盖现有样式。

App.xaml 中(App.Resources element 下)我定义了这样的样式:

<Style TargetType="Button">
    <Setter Property="Padding" Value="6"/>
    <Setter Property="FontWeight" Value="Bold"/>
</Style>

并且在某个Window 的XAML 中,我在Window.Resources 下定义了以下内容:

<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
    <Setter Property="Padding" Value="6"/>
    <Setter Property="FontWeight" Value="Bold"/>
</Style>

这里的问题是前者(app)样式被忽略,就好像后者(window)样式已覆盖它一样。设置了BasedOn 属性,据我所知,它旨在指示应该继承现有样式。删除该属性也无济于事。我能想到的唯一潜在原因是{StaticResource {x:Type Button}} 仅指默认 WPF 样式,而不是我在 App.xaml 中定义的样式。

我知道这种样式行为可以使用x:Key 属性来完成,但我希望有一种更优雅的方式,允许我将具有继承的样式应用于范围内的所有控件(即应用程序/窗口)。

更新

感谢您的两位回复。您确实是对的,在示例应用程序中事情按预期工作。不同的是,我无意中没有提到App.xaml 中的样式包含在ResourceDictionary 中,因此:

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>

            <ResourceDictionary Source="SettingsDictionary.xaml"/>

            <ResourceDictionary>

                <Style x:Key="DefaultButton" TargetType="Button">
                    <Setter Property="Padding" Value="4"/>
                    <Setter Property="HorizontalAlignment" Value="Center"/>
                    <Setter Property="VerticalAlignment" Value="Center"/>
                </Style>

            </ResourceDictionary>

        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

对本案如何补救有什么建议吗?

【问题讨论】:

  • 如果您尝试为窗口创建新的默认样式或控制您声明的第二个样式,则该假设是正确的。在您的特定示例中,默认样式的两个属性都将被覆盖新的默认样式。如果没有继承原始样式的任何属性,则可能会出现不同的问题。您是否有机会动态更改样式属性?
  • @Jeff:我根本没有动态更改样式。事实上,这些是当前在整个应用程序中定义的唯一样式,所以我看不出还有什么可以干扰的。我仍然想知道我是否误解了样式系统...
  • 只是为了确认,为 App 中的样式设置 x:Key 并将 Window 的样式基于它工作得很好。我正在寻找一种方法来避免这种情况,也许使用另一个绑定说明符。
  • 检查我更新的答案,看看是否有帮助。

标签: wpf xaml inheritance styles


【解决方案1】:

Jeff Wains 对您的方法没有按预期工作感到惊讶,这是我第二次发表评论。事实上,我无法通过以下步骤重现您的问题:

  • 通过 VS 2008 C# WPF 应用程序向导创建了一个新项目。
    • 导致 App.xaml 和 Window1.xaml 就像您的示例一样
  • 将工具箱中的标准按钮添加到 Window1。
  • 按原样粘贴您的 sn-ps,分别修改了一个属性以首先观察所需的效果(我猜,每个属性/值都相同,并不是您打算演示的)。

嗯,这很好用,即 Window1 中的按钮从两种样式中继承属性,并且修改任一样式中的属性确实会正确影响按钮。因此,在您的项目/环境中,他们一定是在幕后发生了一些奇怪的事情吗?您是否已经尝试过这样一个简单的复制案例?

【讨论】:

  • 感谢您的回复,尽管 kek444 似乎从我的更新问题中找到了问题。
【解决方案2】:

编辑

经过一番研究,我发现如果设置了 TargetType,则会自动生成 x:Key。所以,App.xaml 中的样式是正确的。但是,wpf 设计器缺乏一些资源处理技能,并且没有显示两种样式。如果您构建并运行项目,两种样式都将被应用。

如果您的机器和 VS2008 的行为与我测试您的代码时使用的一样。

希望这会有所帮助。

编辑 2

App.xaml 中的资源和合并字典一直都很古怪。 我已经通过将第一个样式声明移出合并字典来解决问题,如下所示:

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>

            <!--<ResourceDictionary Source="SettingsDictionary.xaml"/>-->

        </ResourceDictionary.MergedDictionaries>

        <Style TargetType="Button">
            <Setter Property="Foreground" Value="Red"/>
            <Setter Property="Padding" Value="4"/>
            <Setter Property="HorizontalAlignment" Value="Center"/>
            <Setter Property="VerticalAlignment" Value="Center"/>
        </Style>

    </ResourceDictionary>
</Application.Resources>

另请注意,为样式指定除 {x:Type Button} 之外的显式设置键将使其成为非默认样式并使其不会自动应用。

一般建议只为其他文件的资源指定合并字典,如上默认空间中的编码资源。

【讨论】:

  • @kek44:啊!这确实可以解决问题。 (我不敢相信我没有尝试将样式元素放在那个地方;我一定尝试过其他几个。)现在可以看出,无论如何以这种方式定义它们在结构上更有意义。无论如何,非常感谢。赏金是你的。 :)
  • 只是为了完成事情:如果我需要在单独的 ResourceDictionary XAML 文件中定义某些样式(例如在程序集之间共享),是否有任何方法可以使继承仍然正常工作,因为我想来这里吗?
  • 尝试,作为一个实验,将您的第一个 Button 样式放在单独的资源字典中,并在 app.xaml 合并字典中引用它。我还没有检查,但我打赌它会正常工作。重点是让合并的字典真正合并外部文件,否则它可以正常工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-15
  • 2011-07-15
  • 1970-01-01
相关资源
最近更新 更多