首先谈谈resource类型和content类型的区别
BuildAction属性设置为Conten的文件将被作为独立文件直接打包在xap文件中
BuildAction属性设置为Resource的文件将被嵌入到xap包中的dll文件内
BuildAction属性设置为None的文件,将不会存以任何形式在于xap包
那么前两者有什么区别呢
多数情况下,两种形式都可以使用,但是以下情况使用Content更为便捷:
一般情况下,使用Content时,资源文件的URI更为简洁,而Resource相对繁琐一些。
e.g.如video1.wmv文件通常可通过URI“/Medias/video1.wmv”访问,
而video2.wmv则需要“[项目名];component/Medias/video1.wmv"访问(XAML中除外)
由于使用Content时,文件是直接打包在项目中,因此对于需要批量打包生成xap文件的场景,只能用Content。
对于多媒体文件,务必使用Content形式以取得更佳的性能。
MSDN文档原文:
“Media processing on Windows Phone 7 is optimized to use files and network streams, but not in-memory streams. This means that any media files included in the application, such as sound effects, should have their Build Action set to Content and notResource.”
“Windows Phone 上的多媒体处理针对文件和网络流做了优化,而内存流没有。这就意味着包含在应用程序中任何媒体文件,如声音 效果等,应该设置其BuildAction属性为Content而不是Resource。”
对于以下场景,使用Resource可能更合适:
需要避免异步加载的资源文件应当使用Resource
.一个典型的场景是Panorama控件的背景图片,如果设置为Content在首次显示页面时会有闪烁。MSDN文档原文:
If a Panorama control is using an image for the background, its Build Action should be set to Resource; otherwise, it will not appear immediately when the application is first displayed. Setting the Build Action to Content would cause it to be loaded asynchronously.”
“ 如果Panorama 控件使用图片作为背景,其BuildAction属性应当色号之为Resource;否则,当应用程序手册显示时图片将不会立即呈 现。将BuildAction设置为Content属性会导致其异步加载。”
很多用作背景的图片都和上例相仿
使用Resource可以比Content更好的保护自己Xap包中的资源文件(如自己辛苦设计的图片等)。
这很容易理解,因为Content时资源文件直接以文件形式存在于Xap包中,别人拿到Xap解压后也就拿到了你的资源文件。而Resource 时嵌入在dll文件中,获取相对麻烦些(但也不是完全安全)。
需要从C#代码中动态访问的资源文件(如XML文件等),需要设置为Resource。欲了解详情请参考下一课介绍的场景。
扩展知识实际上,不仅是资源文件可以设置BuildAction属性,VS项目中的所有文件都有BuildAction属性,如xaml文件、cs文件等,只是一般情况下我们不需要改动这些文件的BuildAction属性而已。点此了解更多BuildAction相关介绍。
多朋友在论坛发贴抱怨Windows Phone 7中无法将安装文件夹中的文件拷贝到独立存储中。我很理解产生这种需求的来源:很多时候我们希望将自己预先定义好的一些配置文件添加到项目中,然后在用户安装程序后,通过代码将配置文件拷贝到独立存储中;或者在使用一些第三方的基于独立存储的数据库时,也希望能够将预先定义的数据库文件从安装文件夹拷贝到独立存储中。那么这种需求究竟能否实现呢?答案是:完全可以!
疑惑1:如何从安装文件夹拷贝文件到独立存储?大部分朋友在尝试以常规的文件系统操作的方式来访问安装文件夹中的文件中,都会遇到类似如下的错误:
Attempt to access the method failed: System.IO.File.Open(System.String, System.IO.FileMode)
Attempt to access the method failed: System.IO.StreamReader..ctor(System.String, System.Text.Encoding)
也就是读取安装文件夹中文件失败。其实这在Silverlight中是一个正常现象,是Silverligth的安全机制所决定的。在WP7中我们同样无法打破这种安全机制,那么其实我们所讨论的问题的核心,就是如何正常访问安装文件夹中文件?
受安全机制所限,通过文件系统的方式显然是不可能了。但是幸运的是,我们还是有其他变通的方法的,那就是:将要访问的文件设置为资源,然后通过Application.GetResourceStream()方法获得资源文件流。
如要在代码中访问图中所示的“/Data/MyData.txt”文件,可通过如下方法实现。
首先,将文件的BuildAction属性设置为Resource,这样将保证该文件将来会被以资源形式编译到dll中。(关于Resouce和Content的区别及使用,请参考《BuildAction之Content与Resource》一文)。
然后,在代码中就可以通过如下方式取得该文件的文件流。
Stream stream = App.GetResourceStream( new Uri("/DemoCode2;component/Data/MyData.txt", UriKind.Relative)).Stream;既然文件流获取到了,那么对其进行复制操作就是顺理成章的了。如下代码即可将文件复制到独立存储中。
using (FileStream fileStream = IsolatedStorageFile.GetUserStoreForApplication().OpenFile("MyData.txt", FileMode.Create))
{
byte[] bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
fileStream.Write(bytes, 0, bytes.Length);
}
当然,通过GetResourceStream方法也可以解决一些其他类似的问题,如读取安装文件夹中文件。以下代码演示了在获得文件流后读取文件内容并显示。
StreamReader reader = new StreamReader(stream);
string str = reader.ReadToEnd();
借助GetResourceStream方法,即可通过一种变通的方式解决类似的访问安装文件夹中文件(实际编译后已经不再是文件而是嵌入到了dll中)的问题。
疑惑2:是否BuildAction设置为Content的文件就都无法通过C#代码访问了呢?目前看来,大多类型文件设置为Content时是无法通过C#代码访问的。目前看来,仅考虑Silverlight库时,大多类型文件设置为Content时是无法通过C#代码访问的。但个别类型文件例外:
(1)图片文件可以通过URI访问
Uri uri = new Uri("/Data/Jellyfish.jpg", UriKind.Relative);BitmapImage bmp = new BitmapImage(uri);image1.Source = bmp;(2)XML文件可以借助XElement.Load()方法访问
XElement el = XElement.Load("/Data/AllUsers.xml");textBlock1.Text = el.ToString();(3)多媒体文件可以通过MediaPlayerElement访问
疑惑3:是否可能修改安装文件夹中文件?目前看来,无论文件的BuildAction设置为Resource还是Content、无论是何种类型文件,以上两种访问方式都仅限于读取,无法向安装文件夹写入数据。