本文介绍了基础窗口的 WPF 样式未在 App.xaml 中应用,但在 Themes/Generic.xaml 中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为我的大多数窗口创建一个基窗口类以从中派生.显然,最好的解决方案是单独的类,以及适用于它的样式.

I am in the process of creating a base window class for most of my windows to derive from. Obviously the best solution for this was a separate class, and a style that applies to it.

问题是我拥有的 App.Resources 中没有被应用.也就是说,如果它在外部ResourceDictionary中定义,并合并到App.xaml的资源中,或者本地字典并合并,或内嵌到App.资源.但是, 在放入 Themes/Generic.xaml 时应用.

The issue is that the <Style ../> I have is not being applied when it is in App.Resources. That is, if it's defined in an external ResourceDictionary, and merged into App.xaml's resources, or a local dictionary and merged, or placed inline into App.Resources. The <Style ../> is, however, applied when it is placed into Themes/Generic.xaml.

除了覆盖 DefaultStyleKeyProperty 之外,无需在基本窗口中做任何特殊处理即可演示该问题.

The problem can be demonstrated without doing anything special at all in the base window, apart from overriding the DefaultStyleKeyProperty.

下面是ThemeWindow:

public class ThemeWindow : Window
{
    static ThemeWindow()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(ThemeWindow), new FrameworkPropertyMetadata(typeof(ThemeWindow)));
    }
}

这是我正在尝试应用的非常简单的 <Style ../>(它使 Window 背景变为红色,仅此而已):

Here is the very simple <Style ../> I am trying to apply (it makes the Window background red, nothing more):

<Style TargetType="{x:Type testing:ThemeWindow}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type testing:ThemeWindow}">
                <Grid>
                    <Grid.Background>
                        <SolidColorBrush Color="Red"/>
                    </Grid.Background>
                    <AdornerDecorator>
                        <ContentPresenter />
                    </AdornerDecorator>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

使用 ThemeWindowMainWindow,只是以下 XAML:

The MainWindow that uses ThemeWindow, is simply the following XAML:

<testing:ThemeWindow x:Class="Testing.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:testing="clr-namespace:Testing"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Button Content="Button" HorizontalAlignment="Left" Margin="125,83,0,0" VerticalAlignment="Top" Width="75"/>
    </Grid>
</testing:ThemeWindow>

现在,如上所述,如果您将 Style 放在它自己的 ResourceDictionary 中,并像这样包含它:

Now, as stated, if you place that Style in its own ResourceDictionary, and include it like this:

<App.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/Themes/ThemeWindow.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</App.Resources>

...它不起作用.如果您直接将样式内联到 App.Resources 中,则它不起作用.

.. it does not work. If you inline the style straight into App.Resources, it does not work.

我能找到的唯一情况是调用ResourceDictionary xaml Generic.xaml,并将其放入Themes/ 应用程序目录.

The only situation I can find it working is to call the ResourceDictionary xaml Generic.xaml, and place it into the Themes/ directory of the application.

我想知道为什么会发生这种情况.

I am wondering exactly why this is happening.

我唯一的理论是,当 WPF 看到控件类型时,它会转到 Themes,并扫描所有 ResourceDictionary 的类型,然后回退到 Generic.xaml 并加载它.这并不能解释为什么如果 <Style/> 在合并的 ResourceDictionary 中可用,它不会加载.注意,如果将 MergedDictionary 放入 Generic.xaml 中,它确实可以工作,原因很明显.

My only theory is that when WPF sees a control type, it will head over to Themes, and scan all ResourceDictionarys for the type, then fall back to Generic.xaml and load it. This doesn't explain why it would not load if the <Style /> is available in a merged ResourceDictionary though. Note that it does work if the MergedDictionary is placed into Generic.xaml, for obvious reasons.

如果我必须这样做的话,我完全可以将 ResourceDictionary 合并到 Generic.xaml 中.我只想了解一下为什么需要这样的技术细节.

I'm perfectly fine with having to merge the ResourceDictionary into Generic.xaml if that's what I have to do. I just want to get down at the technical details as to why it needs to be like this.

这不工作/工作的截图:

Screenshots of this not working / working:

推荐答案

我有一个简单的解决方法,可以让您在 app.xaml 中设置样式.

I have a simple workaround that would allow you to set your Style in you app.xaml.

像这样在 app.xaml 中定义你的风格:

Define your style in app.xaml like this :

<Style x:Key="{x:Type testing:ThemeWindow}" TargetType="{x:Type testing:ThemeWindow}">

并将您的 ThemWindow 更改为:

And change your ThemWindow to this :

public class ThemeWindow : Window
{
    static ThemeWindow()
    {
        StyleProperty.OverrideMetadata(typeof(ThemeWindow), new FrameworkPropertyMetadata(GetDefautlStyle()));
    }

    private static Style GetDefautlStyle()
    {
        if (defaultStyle == null)
        {
            defaultStyle = Application.Current.FindResource(typeof(ThemeWindow)) as Style;
        }
        return defaultStyle;
    }

    private static Style defaultStyle = null;
}

它并没有真正解决问题,但可以让您实现您所需要的!

It does not really solve the question, but that would allow you to achieve what you need !

查看 DefaultStyleKey 参考,明确说明它用于主题样式查找.这解释了为什么它不会在 app.xaml 或任何其他字典中找到它.它只会在主题词典中搜索.因此,您要么必须在主题词典中定义样式,要么像上面的示例一样直接使用 Style 属性.

EDIT : Looking at DefaultStyleKey reference, it's clearly stated that it's used for theme style lookup. That explains why it won't find it in app.xaml or any other dictionary. It will only search in Theme dictionaries. So you either have to define your style in a Theme Dictionary, or to use the Style property directly as in the above example.

这篇关于基础窗口的 WPF 样式未在 App.xaml 中应用,但在 Themes/Generic.xaml 中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-06 00:50