2014-11-20 84 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> 

查看顯示在設計器中的內容。它可能會給我們一個線索。

相關問題