【问题标题】:WPF, custom controls, and style/theme inheritanceWPF、自定义控件和样式/主题继承
【发布时间】:2025-11-22 12:00:02
【问题描述】:

我正在处理一个已经存在的项目,我无法让样式按我想要的方式工作。

我从一个应用程序开始:

  • Resources 文件夹中有一个 WhistlerBlue.xaml 文件。
  • 文件中的样式使用TargetType自动应用它们
  • Expander 控件定义了一个样式(更多内容,下一个)
  • 我不想弄乱这个文件。
  • 该文件通过 App.xaml 中的合并资源在应用程序中显式使用

到目前为止,一切正常。


那么……

我正在构建一个从 Expander 派生的自定义控件:

internal partial class TestExpander : Expander

通过创建自定义控件,VStudio 已将 Theme 文件夹添加到项目中,其中包含通常的 Generic.xaml 文件。在这个文件中,我为我的自定义控件创建了样式:

<Style TargetType="{x:Type local:TestExpander}" BasedOn="{StaticResource {x:Type Expander}}">
    <Style.Resources>
        <BooleanToVisibilityConverter x:Key="BooleanToVisibility"/>
    </Style.Resources>

    <Setter Property="ExpandDirection" Value="Down"/>
    <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
    <Setter Property="HorizontalAlignment" Value="Stretch"/>
    <Setter Property="VerticalAlignment" Value="Top"/>
    <Setter Property="Cursor" Value="Hand"/>
</Style>

显然在我拥有的自定义控件的代码中:

static TestExpander()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(TestExpander), new FrameworkPropertyMetadata(typeof(TestExpander)));
        }

我希望我的 TestExpander 继承 WhistlerBlue.xaml 中定义的 Expander 样式,通过自己的样式添加它自己的自定义,他们从此过上了幸福的生活。

这没有发生。我哪里错了?

【问题讨论】:

  • 您是否拥有包含您尝试继承的样式模板的资源字典,该样式模板在您的新资源字典 (generic.xaml) 中声明为 ResourceDictionary.MergedDictionaries,以便它可以找到它?跨度>
  • @ChrisW。你是我的英雄。
  • 哈哈,别担心,我们都去过那里。干杯。 :)
  • @ChrisW。是的,但是自从该技术可用的第一天起,我就在开发 WPF 应用程序...我不应该犯这些错误 :-\ 无论如何...发布答案怎么样,这样我可以接受它? xD
  • 当然,如果它让你感觉更好,我只是花了一个多小时试图找出一些东西,同时对多个复杂对象数组中的数据进行一些按摩,以找到一对新的眼睛可能会在几秒钟内发现并称为菜鸟错误哈哈。在我们的业务中保持谦虚是件好事。 :)

标签: xaml wpf-controls


【解决方案1】:

因此,当我们为各种事物创建继承架构时,很容易忘记事物接收其继承部分的顺序。因此,例如,当我们放置一个直接查看 x:Type 的 BasedOn 时,它只会按照可用的继承顺序查找它吗?

当它正在寻找x:Type 并且它不知道另一个字典中的覆盖时......他只是直接进入默认的原件。但是,如果我们通过ResourceDictionary.MergedDictionaries 注入包含您想要继承的内容的字典,那么它知道在他回到框架默认值之前先看看他,一切都很好。

不过,附带说明一下,当您以这种方式合并字典以进行继承时,您必须注意您的操作方式,否则可能会导致性能下降。因为通过说它是一个合并的字典....在运行时它将把字典中的所有内容都合并到新的字典中。

所以对于这种情况....如果是我,我可能会忽略该 generic.xaml 字典内容,如果它不是真的必要的话,并将该模板放在现有字典中它希望从中继承的模板的下方被放置。这样你就不会再复制整本字典了,它仍然会得到它的继承,生活应该是美好的。希望这可以帮助。 :)

【讨论】: