WPF支持两种格式的Resource,即binary resource和logical resource。而Binary resource又有三种方法:可以嵌入在assembly中,编译时才打包的独立文件,运行时的独立文件。至于binary resource的culture属性不在这里讨论。Visual Studio为WPF Project中的Resource定义了Action:

  • Resource: 将指定文件嵌入Assembly。
  • Content:指定文件不会嵌入Assembly,但编译时会打包。通常该选项用在HTML文件直接读取的场合。
  • EmbeddedResource:该选项不应该被使用!

WPF为了能够调用Resource,提供了一套uniform resource identifier (URI)机制。该机制不仅能在Code中直接访问Resource,更可以在XAML中直接调用。然而,这套机制的出台,也为Resource的调用增加了麻烦。

为了说明问题,首先定义一个具体的Scenario。该Scenario如下:App1.exe,调用Mod1.dll。通常App1.exe只是个入口程序,无实际代码,但需要其打包程序所对应的Icon。Mod1.dll则负责具体Window和各种Popup的逻辑。由此可见,有如下两种Resource的调用需求:

  • App1.exe需要封装Icon。该Icon是整个程序级别的。
  • Mod1.dll中的Resource。简单起见,还是用Icon为例。

对于需求1,需要在Resources.resx中将对应的Icon加为资源。为了使该Icon应用在整个程序,需要在Project的Setting中的Application Tab设置Icon信息。如下图所示:

Project Setting

对于需求2,为了配套于MVVM模式,也为了提高Performance,通常在Memory中将对应的Icon缓存起来。根据Resource时候被加入Project,其调用方法也不同。

  • 嵌入在Assembly的Resource。在XAML中调用的示例代码: ```C#

这里,Mod1为该DLL的Assembly Name。'/Resources/cancel.png'是其具体路径。
在Code中,其语法为。
```C#
myImage = new System.Windows.Controls.Image();
myImage.Width = 32;
myBitmapImage = new System.Windows.Media.Imaging.BitmapImage();
myBitmapImage.BeginInit();
myBitmapImage.UriSource = new Uri("pack://application:,,,/Mod1;component/Resources/cancel.png", UriKind.Absolute);
myBitmapImage.DecodePixelWidth = 32;
myBitmapImage.EndInit();
myImage.Source = myBitmapImage;
  • 独立文件。为了方便用户可以自由切换图片,使用独立文件也不失为一种上佳选择,当然,其风险也是不言而喻的,独立文件无法被正常打开时,会导致程序Crash。这里,我们假设应用程序会在运行目录的”Images\Icons”中查找对应的文件。同样,XAML的示例代码: ```C#
;
在Code中,其语法为:
```C#
myImage = new System.Windows.Controls.Image();
myImage.Width = 32;
myBitmapImage = new System.Windows.Media.Imaging.BitmapImage();
myBitmapImage.BeginInit();
myBitmapImage.UriSource = new Uri("pack://siteoforigin:,,,/Images/Icons/Cancel.png", UriKind.Absolute);
myBitmapImage.DecodePixelWidth = 32;
myBitmapImage.EndInit();
myImage.Source = myBitmapImage;

对于MVVM模式,只需要将Button的Content与对应的Image进行Binding。

是为之记。 Alva Chien 2010.12.21