WPF包:/ [assemblyName]; component / ... vs pack:// application:,,, / [assemblyName]; component / ...?

时间:2014-11-20 17:29:57

标签: wpf xaml resourcedictionary

我试图在我正在使用的WPF应用中使用合并的ResourceDictionaries解决问题时遇到了这种奇怪的现象。

我在外部DLL(" common")中定义了自定义控件(TextButton,MenuButton)和资源(颜色,画笔,控件样式和自定义控件模板)。在另一个库中,我有一个使用这些样式的用户控件(" pluginA")。

只要我使用标准的WPF控件(TextBlock,Button,Grid等) - 我就可以应用" common" DLL没有任何问题。设计师会选择风格并正确应用它。

如果我将其中一个自定义控件(TextButton)放入" pluginA"中的用户控件中。 - 设计人员会找到自定义控件,但无法解析要应用的样式的类型(类型引用找不到名为' {clr-namespace:Common}的类型TEXT按钮'。)

我的usercontrol中的xmlns声明如下所示:

<UserControl x:Class="PluginA.Views.LeftBarView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:core="clr-namespace:Common.Core;assembly=Common"
             xmlns:common="clr-namespace:Common;assembly=Common"
             mc:Ignorable="d" 
             d:DesignHeight="600" d:DesignWidth="300">
<UserControl.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <core:SharedResourceDictionary Source="/Common;component/Resources/DefaultTheme/DefaultTheme.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</UserControl.Resources>

通过这个定义,设计师不会应用任何样式 - 但它在运行时工作。太棒了,但不是那么有用,因为我不想运行应用程序来查看是否有小调整生效。

所以我尝试了这个:

<core:SharedResourceDictionary Source="pack://application:,,,/Common;component/Resources/DefaultTheme/DefaultTheme.xaml" />

但这并没有改变任何事情(设计师仍然无法找到资源)。在更改代码的过程中,我得到了这个:

<core:SharedResourceDictionary Source="pack:/Common;component/Resources/DefaultTheme/DefaultTheme.xaml" />

现在设计师很高兴并且可以找到资源 - 运行时很开心并显示资源,但是我找不到任何有关PACK URI的描述......任何人都可以解释为什么这会有效?

1 个答案:

答案 0 :(得分:1)

  

pack:/Common;component/Resources/DefaultTheme/DefaultTheme.xaml

这在技术上是一个有效的URI,但它不是有效的pack URI。根据{{​​1}}格式的规则解析它将产生:

包URI: pack
部分URI:<empty>

实际上,您通过附加/Common;component/Resources/DefaultTheme/DefaultTheme.xaml方案从部件URI中创建了绝对URI。但是,如果没有格式良好的包组件,则结果不是有效的pack: URI。而且,有趣的是,pack类实际上不会将原始字符串解析为绝对URI;它被解析为错误作为相对URI,这是它在分配给Uri时的工作原因的一部分。我们来看看属性设置器:

ResourceDictionary.Source

关键在于public Uri Source { get { return _source; } set { // ... _source = value; Clear(); Uri uri = BindUriHelper.GetResolvedUri(_baseUri, _source); WebRequest request = WpfWebRequestHelper.CreateRequest(uri); // ... } 。那里的逻辑与WPF中的大多数BindUriHelper.GetResolvedUri(_baseUri, _source) URI处理不同,它看到pack不是绝对URI(至少根据损坏的_source类),所以它尝试将它与已解析的基URI(我们假设为Uri)相结合。 URI通过pack://application:,,,/组合,这仅仅因为new Uri(Uri baseUri, Uri relativeUri)错误地将原始字符串解析为相对URI而起作用。最终用于创建Uri的URI等同于:

WebRequest

......产生:

new Uri(
    new Uri("pack://application:,,,/"),
    new Uri("pack:/Common;component/Resources/DefaultTheme/DefaultTheme.xaml"))

而且中提琴,我们最终从有效的包URI加载资源,即使我们给它一个无效的。

我们知道&#34;坏&#34; URI的工作原理是因为它意外地变成了一个好的。至于为什么那么好&#34;好&#34;当设备直接使用时,URI在设计器中不起作用,非常好奇。

也许您只需要重建pack://application:,,,/Common;component/Resources/DefaultTheme/DefaultTheme.xaml 项目和尝试合并资源字典的项目。如果它仍然失败,那么在设计器中运行时Common可能与运行时有UserControl.Resources不同BaseUri。让我们看看我们是否能够弄清BaseUri在设计时的情况。修改您的UserControl,如下所示:

<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             ...
             xmlns:m="clr-namespace:System.Windows.Markup;assembly=System.Xaml"
             x:Name="Root">
  <UserControl.Resources>
    <ResourceDictionary">
      <Style x:Key="BaseUriTextStyle" TargetType="TextBlock">
        <Setter Property="Text"
                Value="{Binding ElementName=Root,
                                Path=Resources.(m:IUriContext.BaseUri)}" />
      </Style>
    </ResourceDictionary>
  </UserControl.Resources>

  <TextBlock Style="{StaticResource BaseUriTextStyle}" />
</UserControl>

查看设计器中显示的内容。它可能会给我们一个线索。