This one has burned me a few times, so here is how it works for future reference: Usually, when I add an Image control into a Silverlight application, and the picture it shows is local (as opposed to loaded from the web), I set the picture’s Build Action to Content, and the Copy to Output Directory to Copy if Newer. What the compiler does then is to copy the picture to the bin\Debug folder, and then to pack it into the XAP file. In XAML, the syntax to refer to this local picture is: <Image Source="/Images/mypicture.jpg"
Width="100"
Height="100" />
And in C#:
return new BitmapImage(new Uri(
"/Images/mypicture.jpg",
UriKind.Relative));
One of the features of Silverlight is to allow referencing content (pictures, resource dictionaries, sound files, movies etc…) located in a DLL directly. This is very handy because just by using the right syntax in the URI, you can do this in XAML directly, for example with:
<Image Source="/MyApplication;component/Images/mypicture.jpg"
Width="100"
Height="100" />
In C#, this becomes:
return new BitmapImage(new Uri(
"/MyApplication;component/Images/mypicture.jpg",
UriKind.Relative));
Side note: This kind of URI is called a pack URI and they have been around since the early days of WPF. There is a good tutorial about pack URIs on MSDN. Even though it refers to WPF, it also applies to Silverlight
Side note 2: With the Build Action set to Content, you can rename the XAP file to ZIP, extract all the files, change the picture (but keep the same name), rezip the whole thing and rename again to XAP. This is not possible if the picture is embedded in an assembly!
So what’s the catch?
Well the catch is that this does not work if you set the Build Action to Content. It’s actually pretty simple to explain: The pack URI above tells the Silverlight runtime to look within an assembly named MyOtherAssembly for a file named MyPicture.jpg in the Images folder. If the file is included as Content, however, it is not in the assembly. Silverlight does not find it, and silently returns nothing. The image is not displayed.
And the fix?
The fix, for class libraries, is to set the Build Action to Resource. With this, the picture will gets packed into the DLL itself. Of course, this will increase the size of the DLL, and any change to the picture will require recompiling the class library, which is not ideal. But in the cases where you want to distribute pictures (icons etc) together with a plug-in assembly, well, this is a good way to have everything in the same place
Happy coding,
Laurent
Laurent Bugnion (GalaSoft)
Subscribe | Twitter | Facebook | Flickr | LinkedIn