web 2.0

News: Windows Phone 7 Phones Running Silverlight


How to Get Files From Resources in Silverlight 2.0

Questions like "How to load an embedded bitmap programmatically?" appear in Silverlight.net forum every single day, and some people actually think it is impossible to do such thing in Silverlight 2.0. Well, the truth is that not only is it possible but it is also damn easy.

Embed a File as Resource 

First thing first: create a new Silverlight Application Project, name it 'SilverlightApplication1'. Add a PNG image file to the project, rename it 'MyImage.png'. Click on the 'MyImage.png' in Solution Explorer to show its properties in Properties Window. 'Build Action' property should be 'Resource' to tell Silverlight compiler to embed 'MyImage.png' file as a resource. The 'Copy to Output Directory' property should be 'Do not Copy'.

 
Hit F5 to build the solution. 'MyImage.png' is now embedded in the application assembly (e.g. SilverlightApplication1.dll).

Load the Embedded File 

The quickest way to load an embedded file is by using the Application.GetResourceStream() method.

VB.NET

Imports System.Windows.Resources       ' StreamResourceInfo
Imports System.Windows.Media.Imaging   '
BitmapImage
... 

Dim sr As StreamResourceInfo = Application.GetResourceStream(_
    New Uri("SilverlightApplication1;component/MyImage.png", UriKind.Relative))
Dim bmp As New BitmapImage
bmp.SetSource(sr.Stream) 

C#

using System.Windows.Resources;      // StreamResourceInfo
using System.Windows.Media.Imaging;  // BitmapImage
....

StreamResourceInfo sr = Application.GetResourceStream(
    new Uri("SilverlightApplication1;component/MyImage.png", UriKind.Relative));
BitmapImage bmp = new BitmapImage();
bmp.SetSource(sr.Stream);

Now you have the embedded bitmap in 'bmp'. Notice the the relative URI. There are literally three parts in the URI. 'SilverlightApplication1' is the name of assembly that has the embedded file. ';component/' is needed as separator, and finally the 'MyImage.png' is the relative path to the image. If the image were in 'Images' subfolder, the URI would be "SilverlightApplication1;component/Images/MyImage.png"

In case you don't know what to do with the bitmap, you can show it in an image element. 

img1.Source = bmp

This assumes that you had added the image element 'img1' to the Xaml file.

Include a File in Application Package Instead

Files can be included in the application .xap package instead of embedded in the application .dll assembly. Remember a .xap file is simply a zip file containing the compiled output files. You can rename the .xap extension to .zip, and then unzip the contents. To include a file in application package, simply set the 'Build Action' to 'Content' and rebuild the solution.

To load the file from the application package:

VB.NET 

Dim sr As StreamResourceInfo = Application.GetResourceStream(_
    New Uri("MyImage.png", UriKind.Relative))
Dim bmp As New BitmapImage
bmp.SetSource(sr.Stream)

C# 

StreamResourceInfo sr = Application.GetResourceStream(
    new Uri("MyImage.png", UriKind.Relative));
BitmapImage bmp = new BitmapImage();
bmp.SetSource(sr.Stream);

Notice the URI is now just "MyImage.png". If the MyImage.png were stored in a subfolder 'Images', the URI would be "Images/MyImage.png". Remember, don't add the slash before the URI. The path "/Image/MyImage.png" would be wrong.

The Visual Studio Bug

If Application.GetResourceStream() returns nothing or null, it may be due to a bug in Visual Studio 2008 that prevents the compiler from rebuilding the resources. You can work around that by go to the project folder, find and delete all the *.resources files in the subfolders. You can also just delete the 'Obj' folder. Now hit F5 to build the solution.

Expect to repeat this workaround everytime you embeded additional files or make change to the 'Build Action' property. Because if you don't, Application.GetResourceStream() might return Nothing or Null. If left unhandled, a 'Null Reference' exception would be thrown.

Tags: ,

Silverlight 2.0 | Tutorial