2009-03-03 78 views
7

我目前正在構建一個由幾個組件組成的應用程序,每個組件都基本上是一個WPF用戶控件,並且周圍有一個小小的C#代碼供插件系統使用(使用MEF) 。從非WPF代碼獲取WPF XAML資源

我遇到的問題是,每個組件都應該包含一個圖標,出於友好的目的,我將其定義爲System.Windows.Media.Brush,因此我可以使用從Design中導出的DrawingBrush。現在我需要訪問非WPF C#那塊XAML的,我現在有實例的用戶控制和要求它爲資源可怕的解決方法:

private Brush CachedIcon = null; 

public override Brush Icon 
{ 
    get 
    { 
     if (CachedIcon == null) 
     { 
      CachedIcon = (Brush)(new BlahControl().TryFindResource("Icon")); 
     } 
     return CachedIcon; 
    } 
} 

我無法找到一個方法來讀取資源(這是一個.xaml文件,並在自定義控件中的ResourceDictionary中引用)來自「普通」C#類。任何屬於WPF的東西都有那麼好的TryFindResource方法,但是如何做到這一點呢?我不想讓XAML文件的圖標處於未嵌入狀態。

回答

2

在您的XAML代碼確保圖標資源具有設置爲「資源」構建選項,然後參考資源,使之成爲XAML的靜態資源

<UserControl.Resources> 
    <BitmapImage x:Key="icon1" UriSource="Resources/Icon1.ico" /> 
</UserControl.Resources> 

然後在.NET 2.0的代碼,你會發現在「{} xamlName .g.resource」資源流

加載從XAML DLL的所有圖標放到一個字典

示例代碼:

using System.IO; 
using System.Reflection; 
using System.Collections; 
using System.Resources; 

... 

var icons = new Dictionary<String, Bitmap>(); 
var externalBaml = Assembly.LoadFile(Path.Combine(Environment.CurrentDirectory, "MyXaml.dll")); 
Stream resourceStream = externalBaml.GetManifestResourceStream(externalBaml.GetName().Name + ".g.resources"); 
using (ResourceReader resourceReader = new ResourceReader(resourceStream)) { 
    foreach (DictionaryEntry resourceEntry in resourceReader) { 
     if (resourceEntry.Key.ToString().ToUpper().EndsWith(".ICO")) { 
      icons.Add(resourceEntry.Key.ToString(), Image.FromStream(resourceEntry.Value as Stream) as Bitmap); 
     } 
    } 
} 
+0

似乎工作,但看起來veeeery hackish。依靠自動生成資源的內部名稱對我來說似乎不太合適。 – Joey 2009-03-11 23:19:51

0

您可以從流中讀取程序集中的資源。

例代碼在這裏: http://www.wpftutorial.net/ReadWPFResourcesFromWinForms.html

+0

嗯,不能得到它現在的工作,稍後將嘗試agani。但是,這並不能作爲解決問題的明智辦法。但是,將Build操作設置爲Resource而不是Page時,顯然XAML文件會作爲XAML嵌入。可能是更好的選擇。我會盡力。 – Joey 2009-03-03 23:28:48

0

在應用級而不是在控制定義的圖標,或者在App.xaml中或主資源字典XAML文件。然後,您可以使用相同的TryFindResource方法,但不創建控件的實例。

+0

由於該項目不是WPF應用程序,而只有用戶控件,因此不存在App.xaml。在只有ResourceDict的情況下,我會在哪裏調用TryFindResource?該圖標已經駐留在一箇中。 – Joey 2009-03-08 17:35:12

1

我的建議是:

  • 在控件上提供關於圖標可以找到的位置的元數據。您可以使用您自己的自定義屬性來完成此操作(請參閱下面的示例1)。此元數據將允許您加載圖標而不創建控件的實例。

  • 由於您使用的是MEF,因此您可以在導出中使用元數據實現與上述相同的功能。詳情here。見下面的例子2。

  • 將您的圖標視爲ImageSource而不是Brush。您可以使用WPF的Image控件來顯示您的ImageSource,或者您可以使用ImageBrush來繪製它。

  • 使用TFD提供的技術以元數據中指定的名稱讀取資源。不幸的是,WPF似乎沒有提供任何類似於BamlReader的東西,這將使它從非WPF上下文中加載WPF資源更加簡潔。

例1:

[Icon("MyIconResourceName")] 
public class BlahControl : Control 
{ 
    ... 
} 

例2:

[Export(typeof(IApplicationComponent))] 
[ExportMetadata("IconResource", "MyIconResourceName")] 
public class BlahControl : Control 
{ 
    ... 
}