2014-11-20 81 views
3

我在尝试使用合并的ResourceDictionaries在WPF应用程序中解决问题时遇到了这种奇怪现象。WPF pack:/ [assemblyName]; component/... vs pack:// application:,,,/[assemblyName]; component/...?

我在外部DLL(“公用”)中定义了自定义控件(TextButton,MenuButton)和资源(颜色,画笔,控件样式和自定义控件模板)。在另一个库中,我有一个使用这些样式的用户控件(“pluginA”)。我只能使用标准的WPF控件(TextBlock,Button,Grid等) - 我可以从“common”dll应用样式,没有任何问题。设计师会选择风格并正确应用。

如果我在自定义控件(TEXT按钮)进入“pluginA”用户控制一个扑通 - 设计师会发现自定义控件,但无法解析样式的类型,应用(类型引用无法找到名为'{clr-namespace:Common} TextButton'的类型)。

在我的用户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 ......任何人都可以解释为什么这会起作用吗?

+0

当您拥有**有效包裹uri **时,您是否尝试重建? – 2014-11-20 18:32:12

+0

对不起 - 被拉到其他东西。我明天开始工作时会试一试。 – 2015-02-02 04:40:12

+0

我将其更改回有效的包URI,并且效果很好。我在当时和现在之间安装了Update 4到VS2013,或许有些事情已经修复,导致它再次按预期工作......?谢谢你的帮助!! :d – 2015-02-02 22:41:46

回答

1

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

这在技术上是一个有效的URI,但它不是一个有效的pack URI。

包URI:<empty>
部分URI:根据pack格式的规则会产生解析它/Common;component/Resources/DefaultTheme/DefaultTheme.xaml

实际上,你已经通过附加取得了绝对URI出部分的URI pack:方案。但是,如果没有格式良好的封装组件,则结果不是有效的pack URI。有趣的是,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); 
     // ... 
} 

关键在于BindUriHelper.GetResolvedUri(_baseUri, _source)。其中的逻辑与WPF中的大部分pack URI处理不同,它看到_source不是绝对URI(至少根据破损的Uri类),所以它试图将它与已解析的基本URI相结合,我们假定为pack://application:,,,/。这些URI通过new Uri(Uri baseUri, Uri relativeUri)合并,仅适用于因为Uri错误地将原始字符串解析为相对URI而起作用。最终被用于创建WebRequest的URI等同于:

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

...主要生产:

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

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

我们知道“坏”URI的工作原理是因为它意外转变成了一个好的URI。至于为什么同样的“好”URI在设计师直接使用时不起作用,那就很好奇。

也许你只需要重建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> 

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

相关问题