2009-03-03 76 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 
{ 
    ... 
}