基本窗口的WPF样式未在App.xaml中应用,但在Themes/Generic.xaml中

Rud*_*ser 10 c# wpf wpf-controls

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

问题在于,当<Style ../>我进入时,我没有被应用App.Resources.也就是说,如果它在外部定义ResourceDictionary,并合并到App.xaml的资源,或者本地字典并合并,或者放入内联App.Resources.的<Style ../>是,然而,应用时,它被放置到Themes/Generic.xaml.

除了重写之外,在基本窗口中根本不做任何特殊的事情就可以证明这个问题DefaultStyleKeyProperty.

以下是ThemeWindow:

public class ThemeWindow : Window
{
    static ThemeWindow()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(ThemeWindow), new FrameworkPropertyMetadata(typeof(ThemeWindow)));
    }
}
Run Code Online (Sandbox Code Playgroud)

这是<Style ../>我想要应用的非常简单(它使Window背景变红,仅此而已):

<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>
Run Code Online (Sandbox Code Playgroud)

MainWindow使用ThemeWindow,仅仅是下面的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>
Run Code Online (Sandbox Code Playgroud)

现在,正如所述,如果你把它Style放在自己的ResourceDictionary,并包括它像这样:

<App.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/Themes/ThemeWindow.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</App.Resources>
Run Code Online (Sandbox Code Playgroud)

.. 这是行不通的.如果你直接将样式内嵌App.Resources,它就不起作用.

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

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

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

我具有合并完全正常的ResourceDictionary进入Generic.xaml,如果这是我必须做的.我只想了解技术细节,了解为什么它需要像这样.

这个不工作/工作的屏幕截图: 破碎的图像 工作形象

Sis*_*phe 3

我有一个简单的解决方法,允许您在 app.xaml 中设置样式。

在 app.xaml 中定义您的样式,如下所示:

<Style x:Key="{x:Type testing:ThemeWindow}" TargetType="{x:Type testing:ThemeWindow}">
Run Code Online (Sandbox Code Playgroud)

并将您的 ThemWindow 更改为:

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;
}
Run Code Online (Sandbox Code Playgroud)

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

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