WPF资源
WPF资源使用其实的也是resources格式嵌入资源,默认的资源名称为"应用程序名.g.resources",不过WPF资源使用的pack URI来访问资源。
添加图像资源
在解决方案资源管理器中包含一个图像资源(如data/img.png)的时候,默认是输出为资源文件的(生成操作=Resource),编译的时候作为资源编译到程序集中;
当在img.png的属性页中把"生成操作"属性设置为"内容",同时设置"复制到输出目录"属性为"如果较新则复制",则输出为内容文件,data/img.png会复制一份到程序集输出目录,这样无需编译就可以修改资源文件了。
此图片资源的uri链接为"/data/img.png",如<Image Name="image3" Source="/data/img.png" />
在资源字典中使用字符串
ResouceDictionary中可以添加各种类型资源,使用如下方法来保存字符串到资源字典中。资源字典默认情况下会被编译成baml保存到"应用程序名.g.resources"资源中,也可以修改输出为内容文件方法同上。
资源字典的xaml代码:
<
ResourceDictionary
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys
="clr-namespace:System;assembly=mscorlib"
>
<
sys:String
x:Key
="rdstring1"
>
resource dictionary string.
</
sys:String
>
</
ResourceDictionary
>
别忘了在app.xaml中添加这个资源字典的引用:
MergedDictionaries
xaml代码中使用此字符串:
<
Label
Content
="
{StaticResource rdstring1}
"
Name
="label8"
/>
代码中使用此字符串:
string
msg
=
(
string
)Application.Current.FindResource(
"
rdstring1
"
);
MessageBox.Show(msg);
加载程序集中的WPF资源
先准备一个WPF资源类库:新建一个程序集,默认创建的东西都删掉,添加上面的资源字典dictionary1.xaml到类库中,编译为ClassLibrary1.dll,使用Reflector工具检查发现这个类库中资源名为:ClassLibrary1.g.resources,内容为dictionary1.baml,ok准备完毕。
主程序集中无需引用这个资源库,只需要放在同一个输出目录下即可,在代码中加载此资源并合并到Application中。
加载代码(相对URI):
var uri
=
new
Uri(
"
/ClassLibrary1;component/Dictionary1.xaml
"
, UriKind.Relative);
var res
=
(ResourceDictionary)Application.LoadComponent(uri);
Application.Current.Resources.MergedDictionaries.Add(res);
加载代码(绝对URI):
var uri
=
new
Uri(
"
pack://application:,,,/ClassLibrary1;component/Dictionary1.xaml
"
);
ResourceDictionary res
=
new
ResourceDictionary {Source
=
uri};
Application.Current.Resources.MergedDictionaries.Add(res);
在XAML中直接加载:
<
Application
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class
="MySampleApp.app"
>
<
Application.Resources
>
<
ResourceDictionary
>
<
ResourceDictionary.MergedDictionaries
>
<
ResourceDictionary
Source
="pack://application:,,,/ClassLibrary1;component/Dictionary1.xaml"
/>
</
ResourceDictionary.MergedDictionaries
>
</
ResourceDictionary
>
</
Application.Resources
>
</
Application
>
使用资源方法同上,注意,后加载的资源会替换掉已有资源中相同名字的资源。
StringTable资源
有时候又大量的字符串资源需要创建,string table文件则是建立此资源的快捷方式。
stringtable内容是一个文本文件,内容格式为key=value/r/n ...,如下所示:
Title=A Simple Application中文
String1=Simple string 中文
Message=Message
然后把文件扩展名修改为.restext,编码为UTF-8,这里命名为data/strings.restext,在程序中引用此文件,同时修改此文件属性为嵌入资源,如图所示:
编译,使用Reflector检查程序集资源会发现多了一个名"MySampleApp.data.strings.resources"的资源,资源内容就是前面创建的strings.restext的内容,如图所示:
读取字符串资源方法和前面一样,只需要指定好资源的命名空间即可。
var rm2
=
new
ResourceManager(
"
MySampleApp.data.strings
"
, Assembly.GetExecutingAssembly());
label6.Content
=
rm2.GetString(
"
String1
"
);
最近学习dotnet多语言资源的设置,很多地方没有搞清楚,于是参考msdn写了点代码验证下想法。
测试程序是一个wpf默认程序,语言和资源均不做设置。
字符串资源
在默认资源文件中添加一条string1=teststring,编译之后用工具查看程序集可以发现字符串资源保存在名为"MySampleApp.Properties.Resources.resources"的资源中,其中MySampleApp为程序集的命名空间,"Properties.Resources"是默认资源文件的名称,".resources"是资源扩展名。
读取此字符串资源代码如下:
//
直接调用资源编辑器生成的类方法
Mywindow.Title
=
MySampleApp.Properties.Resources.string1;
//
或者使用通用方法
var rm
=
new
ResourceManager(
"
MySampleApp.Properties.Resources
"
, Assembly.GetExecutingAssembly());
Mywindow.Title
=
rm.GetString(
"
string1
"
);
读取字符串资源的xaml代码如下:
<
StackPanel
Name
="root"
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:res
="clr-namespace:MySampleApp.Properties"
x:Class
="MySampleApp.MyPage"
>
<
TextBlock
Name
="Text1"
Text
="{x:Static res:Resources.string1}"
></
TextBlock
>
</
StackPanel
>
注意如果想让上面的xaml代码能正常读取系统默认字符串资源,需要设置资源访问属性为public,如图所示:
图片资源
在资源编辑器中添加一个png图片,名为img,资源中的图片格式为System.Drawing.Bitmap。
读取img就是调用rm.GetObject("img"),返回对象是Bitmap类型,此对象无法直接用在WPF的Image控件上,必须做一些转换工作,转换Bitmap为BitmapImage.
var rm
=
new
ResourceManager(
"
MySampleApp.Properties.Resources
"
, Assembly.GetExecutingAssembly());
var bmp
=
rm.GetObject(
"
img
"
)
as
Bitmap;
var stream
=
new
MemoryStream();
var bi
=
new
BitmapImage();
bmp.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
bi.BeginInit();
bi.StreamSource
=
stream;
bi.EndInit();
image1.Source
=
bi;
第二种方法:转换Bitmap为BitmapSource.
IntPtr bmpPt
=
bmp.GetHbitmap();
System.Windows.Media.Imaging.BitmapSource bitmapSource
=
System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
bmpPt, IntPtr.Zero, Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
bitmapSource.Freeze();
DeleteObject(bmpPt);
image1.Source
=
bitmapSource;
[System.Runtime.InteropServices.DllImport(
"
gdi32.dll
"
)]
private
static
extern
int
DeleteObject(IntPtr o);