【问题标题】:Windows Style from ResourceDictionary don't applyResourceDictionary 中的 Windows 样式不适用
【发布时间】:2013-03-03 22:22:15
【问题描述】:

由于我的应用程序中有多个Windows,我正在寻找一种不需要我在每个Window 上设置binding 的解决方案。

我为窗口背景创建了一个ResourceDictionary,其中有一个style

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

在我的XAML 中,我设置了ResourceDictionary

<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Templates.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Window.Resources>

没有错误,但我的Window 颜色保持白色。

【问题讨论】:

  • 请尝试 Application.Resources 而不是 Window.Resources
  • 您的ResourceDictionary xaml 文件是否在项目的根文件夹中?
  • @LPL:它应该仍然可以在Windows.Resources 中工作。
  • @Dan 你确定吗? AFAIK 资源只影响孩子而不是他们自己,不是吗?
  • 我试图在 Application.Resources 中移动它(在 App.xaml 中):没有变化!

标签: c# wpf xaml styles


【解决方案1】:

这是我在应用程序中使用的解决方案。它让我可以将所有窗口样式保持在一起,并且只需要在 &lt;Window.Resources&gt; 部分之后的几行。

你的Style 像这样:

<Style x:Key="MyWindowStyle">
    <Setter Property="Window.Background" Value="AliceBlue"/>
</Style>

然后,在您的窗口中,在&lt;/Window.Resources&gt; 之后包含以下内容:

<Window.Style>
    <Style BasedOn="{StaticResource MyWindowStyle}"/>
</Window.Style>

【讨论】:

    【解决方案2】:

    这似乎是由 WPF 从嵌套的 ResourceDictionary 加载/处理样式的顺序以及 Window 类的细节共同造成的。

    假设 MainWindow 是根据您的帖子定义的。现在将以下内容放入Templates.xaml

    <Style TargetType="{x:Type Window}">
        <Setter Property="Background" Value="Red"/>
    </Style>
    <Style TargetType="{x:Type Window}" x:Key="myStyle">
        <Setter Property="Background" Value="Green"/>
    </Style>
    

    如果MainWindow 没有定义样式,那么您将在设计器中看到它以红色背景显示。设计者正在解析整个 Xaml 并加载资源字典,然后绘制结果。在绘制窗口之前读取样式,因此应用红色背景。

    当您运行应用程序时,会在应用ResourceDictionary 之前创建窗口。它查找默认样式(带有x:Key="{x:Type Window}" 的样式)嵌套的ResourceDictionary 被处理之前,但什么也没找到。因此,在运行时,窗口以默认颜色显示。 (这是上面 cmets 中描述的行为。)请记住,x:Key="{x:Type Window}" 的样式具有与 Windows 样式匹配的默认值。

    如果您明确使用myStyle,则可以证明这一点。如果您将属性 Window 添加到您的 Window 定义中,您会发现设计器失败,但您也会收到运行时错误,因为在窗口需要它的时候还没有创建 myStyle .如果您切换到 Style="{DynamicResource myStyle}",那么您会看到它按您希望的方式工作,因为一旦 ResourceDictionary 被解析并包含样式,DynamicResource 就会更新。

    因此,应用它,您可以通过将其添加到您的 Window 元素以一种方式解决问题:Style="{DynamicResource {x:Type Window}}" - 但这是笨拙的。更好的解决方案是将您的资源字典包含在 app.xaml 文件中,该文件将在打开任何窗口之前对其进行解析,从而可供所有人使用:

    <Application.Resources>
        <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="Templates.xaml" />
                </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
    

    这里真正的问题是您的Window 并不是真正的Window:它是一个派生自Window 的类,实际上是MainWindowWindow2 等... 这意味着Window 的自动样式接线永远不会以这种方式工作,不幸的是总是需要某种程度的手动绑定。

    【讨论】:

    • 非常感谢您的解释。
    【解决方案3】:

    在资源字典中添加新画笔

    <SolidColorBrush x:Key="WindowBackground" Color="AliceBlue" />
    

    在您的 WPF 窗口中,只需将所需资源设置为窗口背景属性

    <Window x:Class="GDD.Presentation.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="300" Width="300"
        Background="{StaticResource WindowBackground}">
    

    【讨论】:

    • 感谢您的回答,但是如果我有多个窗口,我需要为每个窗口设置背景,这就是我想直接使用样式的原因!
    • Downvoted 用于隐式设置 StaticResource。
    • 如果提出问题的人发现合适的答案并接受了它,即使隐式设置了 StaticResource,我也看不出它应该被否决的理由!只有当答案完全不相关或错误时,才应该投反对票,而不是因为有人没有使用最佳实践。
    最近更新 更多