【问题标题】:WPF- Compile error on referencing a Resource Dictionary fileWPF-引用资源字典文件时出现编译错误
【发布时间】:2023-04-01 10:41:01
【问题描述】:

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

未找到自定义窗口样式资源

备注

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

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

编译时出现错误

.

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,0,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>

【问题讨论】:

  • 我遇到了类似的问题。一种解决方法是将其用作 DynamicResource 而不是 StaticResource。

标签: wpf xaml resourcedictionary


【解决方案1】:

您的资源是在加载窗口后加载的,因此在窗口加载事件期间它无法找到资源。所以你的方法不会那样工作。

您需要将该资源放入您的 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>

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

(编辑: 进一步澄清 - 当您将某些内容作为“StaticResource”添加到您的窗口样式中,但稍后加载实际资源时,窗口“已加载”事件不会拾取它. 另一种解决方案是将您的样式称为“DynamicResource”,因此“加载”事件期间的样式不是静态的,并且会在捕获新资源时更新。)

【讨论】:

  • 这个问题更符合我的好奇心,为什么在MainWindow 中引用资源字典不起作用。我已经在App.xamlSource="pack://application:,,,/WPF_OctDelete;component/WindowStyle.xaml" 中尝试过它,它编译得很好。对不起,我应该在我的帖子中提到它。但是感谢您分享您的知识,以便其他人也可以从中受益。您确实值得我为分享您的知识而投票 +1。
  • @nam 我已经回答了你的问题——看看我回答的最上面一行。对我来说不幸的是,您没有阅读我答案的第一行,它准确地解释了您的要求。无论如何,我添加了更多信息。
  • 感谢您指出另一种可能的解决方案。保持良好的工作。我很佩服你分享你的知识。
【解决方案2】:

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>

顺序很重要。

【讨论】:

  • 感谢您解释编译错误的原因——这对我很重要。现在我知道顺序很重要。
猜你喜欢
  • 2014-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-11
相关资源
最近更新 更多