Silverlight 3 new features, pitfalls and oddities

Well, this is my first blog post at this community, and I’m not even going to introduce myself, because that’s what the “About” link on the right is for [:)]. So without further delay, let’s get started with my first post!

When Silverlight 3 was released, i decided to get to know the new features by building an application which needed all of them. In the Flex courses, students would build a somewhat large application called FStop, which is an application to manage and upload photo’s. In the past i tried to port this to Silverlight 2, but some things just couldn’t be done, like saving a photo to the user’s file system in a location of his / her choosing. Now with the release of Silverlight 3, i decided to try it again and i succeeded to implement the whole FStop application with all of it’s features in Silverlight. While building this application i noticed a few oddities / pitfalls related to the new Silverlight features and i decided to share them here. What follows is list of new Silverlight features with the oddities / pitfalls (if any) related to them.

Navigation Framework

  • Default behavior of the Navigation Framework, more specifically the Frame class, is to instantiate and load every page over and over when someone navigates to that page. Even when using the Back button in the browser to return to a previously visited page. If a Page only needs to be loaded once, you can set the NavigationCacheMode property on the Page class to “Required”. Default value is “Disabled”. This property works together with the CacheSize property of the Frame class. Notice that the OnNavigatedTo method always fires, independent of the NavigationCacheMode property.
  • When you put code to force the bindings to update in the OnNavigatedTo Method, controls won’t transition to the Invalid state (or you won’t see that they transition to the Invalid state), which means that you don’t get any visual feedback about data validation. This code should be placed in the Loaded event instead.

SaveFileDialog

  • The SaveFileDialog class has a method “GetStream()” to get a Stream to the location the user has chosen, which you can use to write any kind of data. What’s weird about this stream is that you can use it to write data in a multi threaded application, with other words, you can use the Write methods from different threads than the UI thread. But if you use this Stream in a “using” statement to automatically dispose it from a different thread than the UI thread, you WILL get an exception. It seems that you can write from any thread you like, but the stream needs to be disposed from the UI thread. You can use the RunWorkerCompleted event from the BackgroundWorker class for this.

WritableBitmap class

It’s nice that we can finally make snapshots from components and change pixel data of images, but what if we want to save the changed data to the client using the SaveFileDialog from above? When you just write the pixels from the WritableBitmap to a stream, it’s not in a format any program will recognize. Silverlight doesn’t have any kind of Image encoders (yet), in the mean time you can use this excellent post to save images from the WritableBitmap to a .PNG file.

Application Library Caching

  • To use this feature, you need to create a “AssemblyName.extmap.xml” file in the same folder as the assembly you would like to cache. Next to that, the assembly needs to be signed. If you have met both of these conditions, you can just use the “Reduce XAP Size” option from the project properties in Visual Studio. Visual Studio will create .zip files containing the assemblies in the correct location and update your manifest file. Most of the standard Silverlight 3 assemblies already come with an “extmap.XML” file, but creating those files for your own assemblies or the Silverlight Toolkit (which is an excellent candidate for caching) can be time-consuming. Luckily,  there is a tool which can do this for us, you can find it here.
  • I experimented a bit, creating DLL’s that were 90mb+ (simply embedding large resources) and enable caching on them . What the runtime seems to do is, first download the initial XAP, which is faster because the DLL’s aren’t included. So the Silverlight plugin progress indicator flies to 100 percent. Then it stays at 100 percent while all the external assemblies are downloaded. When this is complete the initial UI of your application shows. It doesn’t matter whether you actually use the assemblies at that time, all assemblies are downloaded when the progress indicator for the initial XAP reaches 100 percent. This way, it is certain that all required assemblies have been loaded, the disadvantage is, you really can’t show any custom progress indication while downloading the assemblies in the background, even worse, your application is unresponsive. It would have been nice if the default progress indication of the Silverlight plugin would somehow show that it was busy downloading assemblies, because just staying at 100%, makes it look like the application has frozen.