WPF-引用资源字典文件时发生编译错误

问题描述

问题:当我在Resource Dictionary文件(如下所示)中引用以下MainWindow.xaml文件时,为什么会出现以下编译错误

找不到CustomWindowStyle资源

备注

  1. 我正在关注这个article,其中Creating A Resource Dictionary File部分还显示了我正在使用的有关如何引用MainWindow.xaml中的资源字典的确切过程
  2. 如下图所示,当我在VS2019中键入CustomWindowStyle行时,Style="{StaticResource ....}确实可以正确识别MainWindow.xaml。但是在编译时(如下图2所示),它会引发上述错误
  3. 我正在使用.NET Core 3.1。我不确定该问题是否与.NET Core有关

在键入行Style =“ {StaticResource ....} 时,智能感知会正确显示选择CustomWindowStyle的选项:

enter image description here

在编译时出现错误

enter image description here

WindowStyle.xaml

<ResourceDictionary x:Class="WPF_OctDelete.WindowStyle"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:WPF_OctDelete">

    <Style x:Key="CustomWindowStyle" targettype="{x:Type Window}">
        <Setter Property="WindowChrome.WindowChrome">
            <Setter.Value>
                <WindowChrome CaptionHeight="30"
                              CornerRadius="4"
                              GlassFrameThickness="0"
                              NonClientFrameEdges="None"
                              ResizeBorderThickness="5"
                              UseAeroCaptionButtons="False" />
            </Setter.Value>
        </Setter>
        <Setter Property="BorderBrush" Value="Black" />
        <Setter Property="Background" Value="Gray" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate targettype="{x:Type Window}">
                    <Grid>
                        <Border Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="5,30,5,5">
                            <AdornerDecorator>
                                <ContentPresenter />
                            </AdornerDecorator>
                        </Border>

                        <DockPanel Height="30"
                                   VerticalAlignment="Top"
                                   LastChildFill="False">

                            <TextBlock Margin="5,0"
                                       VerticalAlignment="Center"
                                       DockPanel.Dock="Left"
                                       FontSize="16"
                                       Foreground="White"
                                       Text="{TemplateBinding Title}" />

                            <Button x:Name="btnClose"
                                    Width="15"
                                    Margin="5"
                                    Click="CloseClick"
                                    Content="X"
                                    DockPanel.Dock="Right"
                                    WindowChrome.IsHitTestVisibleInChrome="True" />


                            <Button x:Name="btnRestore"
                                    Width="15"
                                    Margin="5"
                                    Click="MaximizeRestoreClick"
                                    Content="#"
                                    DockPanel.Dock="Right"
                                    WindowChrome.IsHitTestVisibleInChrome="True" />

                            <Button x:Name="btnMinimize"
                                    Width="15"
                                    Margin="5"
                                    VerticalContentAlignment="Bottom"
                                    Click="MinimizeClick"
                                    Content="_"
                                    DockPanel.Dock="Right"
                                    WindowChrome.IsHitTestVisibleInChrome="True" />
                        </DockPanel>

                    </Grid>

                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

MainWindow.xaml

<Window x:Class="WPF_OctDelete.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPF_OctDelete"
        mc:Ignorable="d"
        Style="{StaticResource CustomWindowStyle}"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="WindowStyle.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
    <Grid>
        <Button x:Name="btnTest" Content="Test"/>
    </Grid>
</Window>

解决方法

您的资源是在加载窗口之后加载的,因此在窗口加载事件期间找不到资源。因此,您的方法将无法正常工作。

您需要将该资源放入App.xaml文件中,请参阅-How to Set the Source of an Image in XAML and in Code Behind to an image in another project in WPF

以您的情况(在App.xaml中)-'

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

然后您可以在窗口中使用密钥-

<Window x:Class="WPF_OctDelete.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPF_OctDelete"
        mc:Ignorable="d"
        Style="{StaticResource CustomWindowStyle}"
        Title="MainWindow" Height="450" Width="800">
    <!--Rest of your UI Elements-->
</Window>

由于窗口已添加到主应用程序文件中,因此无需向其添加资源。该资源将在整个项目中可用(可用于其他Windows /控件)

编辑:进一步说明-当您将某些内容作为“ StaticResource”添加到窗口样式中,但稍后再加载实际资源时,窗口“ loaded”事件将不会进行处理。另一个解决方案是将您的样式称为“ DynamicResource”,因此“ loaded”事件期间的样式不是静态的,并且在捕获新资源时将进行更新。)

,

XAML处理器从上到下读取XAML文件,因此在尝试解析CustomWindowStyle资源时,它尚未加载ResourceDictionary

您可以在设置Resources属性之前,先设置Style属性 来解决此问题:

<Window x:Class="WPF_OctDelete.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPF_OctDelete"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="WindowStyle.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
    <Window.Style>
        <StaticResource ResourceKey="CustomWindowStyle"/>
    </Window.Style>
    <Grid>
        <Button x:Name="btnTest" Content="Test"/>
    </Grid>
</Window>

顺序很重要。