【问题标题】:Organizing Xaml - Unable to apply StaticResource from different xaml file组织 Xaml - 无法从不同的 xaml 文件应用 StaticResource
【发布时间】:2015-05-15 23:43:47
【问题描述】:

我遇到的情况是 wpf 应用程序无法获取 StaticResource,而是因 XamlParseException 而失败。但是,如果我改用 DynamicResource,则会找到资源并且不会发生异常。

我正在尝试按照http://projekt202.com/blog/2010/xaml-organization/ 的建议设计和组织 wpf 资源

相应地,我有 2 个项目,一个包含所有资源的 wpf 控件库和一个使用这些资源的主 wpf 项目。这是两个项目的结构

Projects Structure

Wpf_Theme.ControlLibrary
--资源字典
----BaseControlStyles
------ButtonStyle.xaml
------TextBoxStyle.xaml
----画笔
------默认蓝色主题
----ResourceLibrary.xaml
Wpf_Theme.Main
--App.xaml
--MainWindow.xaml


Contents of xaml files

ButtonStyle.xaml

<Style TargetType="{x:Type Button}">
    <Setter Property="Background"  Value="{StaticResource ControlBackground}"/>
    <Setter Property="BorderBrush" Value="{StaticResource BorderColor}"/>
    ...
</Style>

DefaultBlueTheme.xaml(画笔)

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <SolidColorBrush x:Key="PanelBackground" Color="#C8DCF0"/>
    <SolidColorBrush x:Key="BorderColor" Color="#6A8FB5"/>
    <SolidColorBrush x:Key="SelectedItemBackground" Color="Wheat"/>
    <SolidColorBrush x:Key="TextForeground" Color="Black"/>

    <LinearGradientBrush x:Key="ControlBackground" StartPoint="0,0" EndPoint="0,1">
        <LinearGradientBrush.GradientStops>
            <GradientStop Offset="0" Color="#DBECFD"/>
            <GradientStop Offset="0.5" Color="#C7DBEF"/>
            <GradientStop Offset="1" Color="#B0CAE5"/>
        </LinearGradientBrush.GradientStops>
    </LinearGradientBrush>
</ResourceDictionary>

ResourceLibrary.xaml(将所有字典合并到一个文件中以供主项目使用)

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="Brushes/DefaultBlueTheme.xaml"/>
        <ResourceDictionary Source="BaseControlStyles/ButtonStyle.xaml"/>
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

App.xaml(在主项目中)

<Application x:Class="Wpf_Themes.Main.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary 
                    Source="/Wpf_Themes.ControlLibrary;component/ResourceDictionaries/ResourceLibrary.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

MainWindow.xaml

<Window x:Class="Wpf_Themes.Main.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">

    <StackPanel Width="200" Margin="10">
        <Button>Click Me</Button>
    </StackPanel>
</Window>

如帖子前面所述,我无法使用 ButtonStyle 中应用的 StaticResource 解析 Button 的样式(背景和边框画笔) .xaml。如果我改用 DynamicResource,则会正确找到画笔并将其应用于按钮。为什么会发生这种行为的任何见解。


编辑:
按照 Mike 的建议,我将 Wpf_Theme.ControlLibrary 项目中的 xaml 文件直接包含到 Main 项目的 App.xaml 中,如下所示

App.xaml

<Application x:Class="Wpf_Themes.Main.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/Wpf_Themes.ControlLibrary;component/ResourceDictionaries/Brushes/DefaultBlueTheme.xaml"/>
                <ResourceDictionary Source="/Wpf_Themes.ControlLibrary;component/ResourceDictionaries/BaseControlStyles/ButtonStyle.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

现在可以使用 StaticResource 正确定位资源

【问题讨论】:

  • 您是否有任何特殊原因需要使用您的 ResourceLibrary.xaml 文件?你能不能只合并 App.xaml 中的所有字典?
  • 其实我是在关注前面提到的那个网站。我认为它在那里是为了避免包含 xaml 的程序集 uri 语法。而是使用 esourceLibrary.xaml 嵌入单个文件。有趣的是,如果我避免使用 ResourceLibrary.xaml 而是将所有字典直接嵌入到 App.xaml 中,它就可以正常工作并且资源也可以正确定位。不知道为什么!

标签: c# wpf xaml


【解决方案1】:

静态资源引用在解析时解析(大部分),而动态引用在运行时解析。这意味着静态引用只能在资源在引用之前被解析的情况下使用,而动态引用可以用作稍后定义的资源的前向引用。

来源:http://drwpf.com/blog/category/resources/

当两个 ResourceDictionaries 在一个单独的程序集中并且您同时引用它们时,我猜想这个处理是同时发生的。而如果您直接在 App.xaml 中加载它们,则可以确保它们以正确的顺序加载。

因此,您的第一个词典的资源不适用于第二个词典,因为您将它们包含在同一个词典中。

有两种方法可以解决问题。您可以使用在运行时评估的 DynamicResources(就像您已经尝试过的那样)。

另一个解决方案,如果您现在的资源字典有一定的难度,您可以执行多个级别。喜欢:

<Application x:Class="WPF_Theme.App"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         StartupUri="MainWindow.xaml">
<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="pack://application:,,,/ControlLibrary;component/ResourceDictionaries/BaseLevel.xaml" />
            <ResourceDictionary Source="pack://application:,,,/ControlLibrary;component/ResourceDictionaries/SecondLevel.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

BaseLevel.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="Brushes/DefaultBlueTheme.xaml" />
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

SecondLevel.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ResourceDictionary.MergedDictionaries>
          <ResourceDictionary Source="BaseControlStyles/ButtonStyle.xaml" />
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

DefaultBlueTheme.xaml 和 ButtonStyle.xaml 保持不变。

这样,您可以确保不同的 ResourceDictionaries 在您需要时已经存在。

希望对你有帮助。

【讨论】:

  • 正如对 Mike 的回复的评论中指出的那样,我现在直接在主项目的 App.xaml 中合并字典(ButtonStyle.xaml,DefaultBlueTheme.xaml,...),并且效果很好.请参阅我的问题的编辑
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多