When loading files in Silverlight 2 applications, this can range from images, video, fonts, etc, there are several options available. You might want to call files that reside on another server, files that are embedded into the .xap application or zip files that are downloaded and unpackaged on the client. In this post I’m reviewing the different options available for this, differences between them and how to implement each of the options.
As an example to load the files I’m using a UserControl with an image on it. A very simple example that is clear enough to show the different approaches. All of the examples I'm showing here have a XAML based approach with a code based counterpart, except for the sample for on demand download.
<Grid x:Name="LayoutRoot" Background="White">
<Image x:Name="imageElement" Stretch="Uniform" />
This just displays the image, nothing more:
In other words, this is the default location of your .xap file, so files that are located in the same directory as the base application. By default when you create the Silverlight application with a test web site in Visual Studio this is the ClientBin directory. No extra code is needed to load files in this location.
If the file is placed in the ClientBin directory, call the file in XAML:
<Image x:Name="imageElement" Stretch="Uniform" Source="_DTH8643.jpg" />
Or in code:
imageElement.Source = new BitmapImage(new Uri("_DTH8643.jpg", UriKind.Relative));
Note: for the above sample you can use a forward-slash preceding the image name to express that it is located relative to the .xap file (same directory in this case). This is important to not as here it is not the root of the domain name (absolute path) that is taken into account. Take this example where I have a sub-directory to ClientBin, I’m referencing the file as /images/imagename.jpg.
To reference the file in the images directory in the ClientBin:
imageElement.Source = new BitmapImage(new Uri("/images/_DTH8643.jpg", UriKind.Relative));
First time I used this it caused some confusion as I'm used to referrring to files in the root of the domain in this way, not in a sub-directory, so it's important to note this difference with Silverlight.
Copying files to ClientBin upon build in Visual Studio
In the case you are using the files directly in your Silverlight application and don't want to copy them manually to the ClientBin directory you can set this in Visual Studio. Note this is a copy to the ClientBin directory of the Silverlight application project, not the test web project you may have created.
Build action: None.
Copy to Output Directory: Copy always.
Loading files located outside of ClientBin (.xap location) directory
In the above screenshot I have an image files located in the "images2" directory. To load images from that directory I can enter the full URL of the image:
<Image x:Name="imageElement" Stretch="Uniform" Source="http://localhost:55907/SLLoadResourcesApproaches_Web/images2/_DTH8643.jpg" />
In C# code:
imageElement.Source = new BitmapImage(
new Uri("http://localhost:55907/SLLoadResourcesApproaches_Web/images2/_DTH8643.jpg", UriKind.Absolute));
Referencing files on external web sites
If you want to call images that reside on external sites you can use the standard download method by using WebClient. Remember that cross domain restrictions apply.
Other than that it is just like calling images using the full URL like above.
imageElement.Source = new BitmapImage(new Uri("http://farm3.static.flickr.com/2013/2438725399_4fa3c6eb2f.jpg?v=0", UriKind.Absolute));
There is however maybe a better way to load a file in from an external site where you can better control the loading of your file before showing it in the UI. By using the WebClient class you can download external files on demand, be it from the current origin site or external sites (see below notes on cross domain restrictions). Using the WebClient you can control what to display while the image or file is being downloaded using event handlers. This approach however is not available in XAML but only in code.
1. Create a WebClient object, an OpenReadCompleted event handler and start the download process
WebClient webClientImgDownloader = new WebClient();
webClientImgDownloader.OpenReadCompleted += new OpenReadCompletedEventHandler(webClientImgDownloader_OpenReadCompleted);
2. Set the source to the image in the OpenReadCompleted event handler
void webClientImgDownloader_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
BitmapImage bitmap = new BitmapImage();
imageElement.Source = bitmap;
When you need your Silverlight application to be independent of any files stored on the server separately you can include everything into a single .xap file. The same applies to file that are integral part of the application. If you know a certain file is always used when running the application it makes sense to include it in the .xap file as there is no reason to download it separately. Including files to be part of the package is what we call Content files.
Files that are packaged into the .xap file need to have the Build Action in Visual Studio set to "Content".
To call the file from XAML:
<Image x:Name="imageElement" Stretch="Uniform" Source="/_DTH8643.jpg" />
Calling from code:
imageElement.Source = new BitmapImage(new Uri("/_DTH8643.jpg", UriKind.Relative));
Because the files is located at the same level in the application package as the assembly in which the code is running, the forward-slash preceding the name is required here as well.
Files can also be located in sub-directories of the application package. You will notice that the directories are also included in the .xap file (as they would in any .zip archive file).
As with other .NET assemblies, files can be embedded into the assembly as resources. For Silverlight applications, set the file Build Action to Resource.
Referencing resources embedded into the assembly is implemented in the same way as loading files included in the application (.xap). The difference is they are added to the DLL and thus no longer visible in the .xap file if you unzip it.
This is working well for the current assembly but if you want to use a file located in a referenced assembly (a Silverlight class library) you will need to add a special reference to indicate the assembly you are calling the file from. This is done by adding the following prefix to calling the file:
So, in the example below I'm calling an image from the assembly named ReferencedSlLibrary.
<Image x:Name="imageElement" Stretch="Uniform" Source="/ReferencedSlLibrary;component/_DTH8643.jpg" />
imageElement.Source = new BitmapImage(new Uri("/ReferencedSlLibrarys;component/_DTH8643.jpg", UriKind.Relative));
VS 2008 - SL 2 Beta 1 note: you will notice that the image does almost only get displayed in the Visual Studio designer if you set the source in the above manner, even for own assembly files. I'm guessing this is a bug in beta 1.
To embed fonts there is actually a specific implementation to call upon font files, see this great post by Tim Heuer on the different ways to do this.
PingBack from http://microsoftnews.askpcdoc.com/visual-studio/different-ways-for-loading-images-and-files-in-silverlight-2-applications
In one previous blog I discussed about uploading applications or video asset files to a Silverlight Streaming
(This information relates to Silverlight 2 Beta 2) What does XAP mean? XAP (pronounced ZAP) is the file
One question we receive very often from our customers, is how to load an image, fromdifferent relative
This is the worst designed piece of functionality I have seen in C# for a while. I have implemented some code as listed in this article but it's not working.
The proper way for these classe would be to throw an exception if it can't load the image and tell you what's wrong.
Instead, I'm presented with a blank image and all I can do is scratch my head because everything looks ok to me and Silverlight won't tell what's wrong either.
How can I load programatically an image from a local path without include it in the Project ?? for example: C:/Images/TestImage.jpg
@Cristobal: you can load local images (My Pictures) only in Elevated Mode, however this is out of the browser. More info here:
great work... This saves me a lot of time...
@Katrien DG you could use the OpenFileDialog in SL5 to get a stream for the selected file