While I was at the Silverlight Atlanta Firestarter event I had a chance to meet some great people.  One of them was Sergey Barskiy.  Sergey was doing a session on deployment and while in the speaker area we were chatting about overall feedback on Silverlight.  One of the things he mentioned was what he thought was a bug in Visual Studio Tools for Silverlight.  It was around RESX files and the modifier setting (Internal, Public, etc.).  More on that later.  Sergey was using RESX files for localization.  While investigating the bug for him, I realized how many people might not know how to do some simple string localization/binding in their Silverlight applications.  It’s relatively simple and I thought I’d outline the steps.  I must admit that I’ve never had to develop a full-fledged internationalized application before, and I applaud those who have and have tackled both the obvious of the language localization challenges as well as cultural and display challenges with various technologies.

The Sample Application

For this experiement we’ll keep it simple and we’re talking about String localization.  We are going to work with a Silverlight 3 application in simple form which will have a TextBlock and a Button control which will have their respective Text and Content settings.  Here’s the English-US (en-US) version of the app:

Sample application image

If we were like most applications we’d be done…but this post will try not to be so US-centric :-).

Step 1: Adding default String resources

As a best practice for String resource localization, in your Silverlight application structure, organize your resource files accordingly.  We’re going to use the RESX file approach and let the framework do most of the work for us.  To that regard in my application I have created a folder called Resources and will be placing my RESX files there.  I’ll first add the default set of data, adding a new RESX file named Strings.resx.

When you add this you’ll notice you get a Strings.resx and a designer (cs or vb) file.  By default the Resource Designer will open and we’ll add two values: WelcomeMessage and ButtonMessage.  Our surface looks like this:

Visual Studio resource designer

Notice the Access Modifier section in the designer.  We need to set this to Public in order to use it in binding we will do later, so set it now.  We save this and step one is done.  Let’s test it out and use it.

Step 2: Binding our RESX files to our XAML

Now that we have a Strings.resx file (which is marked as Embedded Resource by default) in our Resources folder, we can use it as a resource in our XAML.  We need to do a few things to enable this.  First, we need to add an XML namespace to our XAML page.  I’ve chosen local for mine, but choose whatever.  We will have this namespace point to our Resources namespace in our application.  Mine looks something like this:

   1: xmlns:local="clr-namespace:StringLocalization.Resources"

Now I can use that assembly classes in my XAML.  I’ll add the Strings class to my UserControl’s Resources section giving it a key of LocStrings like this:

   1: <UserControl.Resources>
   2:     <local:Strings x:Key="LocStrings" />
   3: </UserControl.Resources>

And now I have a XAML resource I can bind to.  Let’s do that.

Step 3: Binding to the resx file data

My XAML has a TextBlock and a Button I want to bind to the string values.  Because I have a XAML resource this is simple and I just create a binding using the the XAML binding syntax to that resource.  here’s what my TextBlock and Button look like (relevant portions):

   1: <TextBlock Text="{Binding Source={StaticResource LocStrings}, Path=WelcomeMessage}" />
   2: <Button Content="{Binding Source={StaticResource LocStrings}, Path=ButtonMessage}" />

Notice that I’m using a Path that points to the String name in the RESX file.  Let’s run the application now and we should see what we’re looking for right?

WRONG.  Here’s the bug that Sergey was talking about.  It turns out that there does seem to be a bug in Visual Studio with regard to the modifier, and more specifically the PublicResXFileCodeGenerator custom tool that is used to generate the code.  It turns everything in the resource to public except the constructor.  Not having the constructor public (it is still marked internal) is what is causing our problem. 

NOTE: This is not a bug in Silverlight or in the Silverlight tools, but more widely in Visual Studio.  The same thing reproduces on any VS project type.  It’s been noted and is being tracked to address.  See this topic:

What we have to do as a workaround is to go into the Strings.designer.cs file manually and change the constructor from internal to public.  I will note that each time you open up the designer for that main resource file that it may get reset to internal, so remember that. 

After changing to public you can run the application and get the desired output.  There is actually a way to still use the resources and keep the constructor internal, but it involves using another class you have to create and instantiate…more on that later.

Step 4: Adding additional localized resources

Now that we have our base working, we simply need to provide the localized resources for our application.  I’m choosing to localize in Spanish (es-es), French (fr-FR), German (de-DE) and Japanese (ja-JP). 

I solicited some help on Twitter to get some “human” translation to double-check my translated text with Windows Live Translator.  To my surprise, Windows Live Translator actually did a great job.  I think with short sentences it is fine, but longer conversational text may lose context.

Thanks to: Ken Azuma, Othmane Rahmouni, Talya, Misael Ntirushwa, Hannes Preishuber, and others who jumped in to offer help for my little sample.

To do this we simply add more resource files into our project following a specific naming scheme.  Since we have Strings.resx when we add additional languages we’ll add them as Strings.<locale>.resx.  So adding German would be Strings.de-DE.resx and so forth.  It really is best to use the xx-xx locale settings versus just the two character (i.e., de) ones.  Note when you add these files to the project that your modifier section in the resource designer should say No Code Generation automatically.  If it doesn’t, choose that option.  We only need the code for our default language choice.  When I’m done my structure looks like this:

Project structure with localized string resx files

Obviously the contents of the file contains the localized string information.  Note that the string parameter names still have to match.  So even though I’m localizing the contents of WelcomeMessage, in the German resource the parameter is WelcomeMessage and not Wilkommen or something like that.

UPDATE: Forgot one critical step – oops.  You have to manually edit your **proj (csproj/vbproj) file for your Silverlight project to add the locales in the SupportedCultures node of the proj file.  This is a manual step (and sucks), but don’t forget it or nothing will work as you suspect.

Step 5: Testing it out.

Because we used our declarative binding in Steps 2-3, we don’t have to change our code.  We should test it out to make sure it works though.  There are two good ways I have found to test this out.  First, the Silverlight plugin supports forcing a UICulture and we could do it that way.  Let’s test German.  In our plugin instantiation on our hosting page we’ll add these two parameters to the <object> tag (relevant portions):

   1: <object ...>
   2:     ...
   3:     <param name="culture" value="de-de" />
   4:     <param name="uiculture" value="de-de" />
   5:     ...
   6: </object>

That tells the plugin to load with those cultures set.  You can change them without recompiling your application and the language will change.

A second option would be to actually change the display language of your Windows environment.  For some this may be a little frightening as your screen suddenly may change to a language you don’t understand natively.  I recommend if you go this route to keep a translation dictionary handy find your way back (you have to logoff/logon to change a display language)!

Either way when you run the application using either of these methods you should get what you expect.  Here’s my German output:

German localized sample application

Obviously it is easier to test using the <param> approach (changing display languages in Windows requires a logoff), but ultimately I recommend doing actual OS display language for verification.  If a user is on a language culture that you have not localized, it will use the default values provided in our initial Strings.resx file.

Another option for testing is that you can actually change the culture and UICulture values using the Thread namespace APIs in Silverlight.  Keep in mind though changing these values on the CurrentThread does *not* reload the default resource, so you’d have to do some additional code to get the resource to load using that new culture setting.

Caveats and cultural differences

One thing to note is that while your application may now have an easy ability to display localized string data with simple bindings, it may not always be appropriate.  Take for instance Japanese language translation (I’ll assume it is roughly translated correctly, but for the sake of this discussion this serves a purpose) of “Click here” for the button.  In English it fits fine in our lovely world of fixed width button sizes.  But look at the Japanese translation of the text:

ここをクリックしてください。

And here’s how it looks in the button:

Japanese localized sample output

Notice that we don’t see all of the characters?!  These are things that you’ll have to understand when things seem simple enough.  Sometimes translated strings will be longer/shorter than your intended design.  Designing around a localized approach will have to consider these in advance.  In fact, for some languages you may have an alternate placement of controls even to accommodate the culture.

As I noted that I used machine translation for my sample here, but I do want to stress that I think respecting cultural differences is important in customer facing applications.  Using something like Windows Live Translator seems simple enough and might work in simple instances, but I would recommend hiring true localization resources/people to help you differentiate the subtle differences in languages.

Public modifier workaround and dynamically setting the culture

As I mentioned above there is a workaround to the internal/public modifier bug.  It is easy enough to change of course, but you may want to look at this approach as well…and in some implementations this may fit within your model better.  The idea is to provide your own class implementation access to the Strings resource.  Here’s an example of what my custom class implementation might look like:

   1: public class CustomResources : INotifyPropertyChanged
   2: {
   3:     private static StringLocalization.Resources.Strings _strings = new StringLocalization.Resources.Strings();
   4:     public StringLocalization.Resources.Strings LocalizedStrings
   5:     {
   6:         get { return _strings; }
   7:         set { OnPropertyChanged("LocalizedStrings"); }
   8:     }
   9:  
  10:     #region INotifyPropertyChanged Members
  11:  
  12:     public event PropertyChangedEventHandler PropertyChanged;
  13:  
  14:     private void OnPropertyChanged(string propertyName)
  15:     {
  16:         if (PropertyChanged != null)
  17:         {
  18:             PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  19:         }
  20:     }
  21:     #endregion
  22: }

And then my resource section would look like this:

   1: <UserControl.Resources>
   2:     <localCustom:CustomResources x:Key="CustomLocStrings" />
   3: </UserControl.Resources>

And my binding would look like:

   1: <TextBlock Text="{Binding Source={StaticResource CustomLocStrings}, Path=LocalizedStrings.WelcomeMessage}" />
   2: <Button Content="{Binding Source={StaticResource CustomLocStrings}, Path=LocalizedStrings.ButtonMessage}" />

Now that I have this in place like this I get around the internal modifier issue because I’m actually binding to an instance of my own class (which has a static instance to the Strings resource class).  Using this method I could dynamically change the culture on the fly as well by resetting the culture settings in the thread and resetting the resource.

   1: ComboBoxItem item = ChangeLog.SelectedItem as ComboBoxItem;
   2: Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(item.Content.ToString());
   3: Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(item.Content.ToString());
   4: ((CustomResources)this.Resources["CustomLocStrings"]).LocalizedStrings = new StringLocalization.Resources.Strings();

A bit of a workaround for most scenarios I think.  I think probably remembering to change the modifier may work best for most cases, but this custom instance class might actually fit better into some model implementations.

Summary

Hopefully you can see that for simple string resources the technical implementation is fairly simple.  The real challenge is to you, the developer, to ensure the cultural integrity of the message is being displayed appropriately.  Localization is not an overall easy task and I’m simplifying it to simple strings here.  As I stated above, I applaud those who have successfully implemented fully localized applications.  It can be as simple as a button label or as complex as alternate screen layouts for different cultures!

You can download the code for this post here: StringLocalization.zip

Hope this helps!


This work is licensed under a Creative Commons Attribution By license.

UPDATE: Michael has posted a comment here and offered himself up to the gauntlet and apologized for his article.  He writes below:

Tim did me a favor with this article, and his comments on Connected Internet. I have left the article up on Connected, because frankly, I deserve the lumps I get over it.

Anyone who has spent more than 5 minutes talking with me, reading this blog, or listening to me on podcasts (Herding Code, Thirsty Developer, Misfit Geek) will know that I LOVE Microsoft.  I’m not ashamed to admit it and I’m not ashamed about my passion for the company or technology it produces.  I’m also not afraid to admit when and where we suck.  I don’t use every Microsoft product…if there are ones that I feel are better for how I use them, then I pick the better tools/technology.  There, bias stated.

I also think that I’m a fair person when it comes to comparisons and reviews and answering questions about competition, etc.  I welcome those conversations.  When I participate in them I do my best to be informed or point out where I’m not informed.  When not informed I try not to make definitive opinions until I have been informed by research or in trying it out for myself.

So you could imagine (like others) that I get frustrated when I see, hear, read things based on bad information, and what seems like no research has been done.  I’ve got thick skin, can usually comment and brush it off.  But today I read something that just triggered a twitch response in me that is making me reply.  It isn’t because of this post only, but because others have written articles on Silverlight that have used the same ill-informed bias.  The one that got me today was from Michael Lankton written for Connected Internet titled 10 Reasons Why Flash is Better than Silverlight.  Michael’s bio talks about him being an AV enthusiast and a corrections officer.  It briefly talks about him having ‘some coder and sysadmin in his history’ – here’s the full bio:

About the Author: Michael was a bass player in a hardcore punk band in the 80's and spent the 90's building and riding custom Harleys. As strange a combination as it may seem, Mike also has some coder and sysadmin in his history as well. At 43 Mike's now a husband and dad, and works as a Corrections Officer in a maximum security lockdown unit by day, and is admin at AV Enthusiast and contributor to Connected Internet when time allows. Mike is also passionate about food and travel.

So, bravo for Connected Internet for picking someone acutely aware of the landscape of the RIA space to do this comparison.  Oh wait.

A few people have commented on the post and JC being first had a lot of good points, refuting most of the bad information but Michael hasn’t corrected anything (despite saying so).  I’ve posted a comment offering to provide accurate information for him (and I’ll extend to anyone) in doing an evaluation.  You should be informed about the capabilities before doing things like this.  In that spirit, since there are some common misconceptions noted in Michael’s post that are incorrect, I had a moment of thought to note them (which others have already added their comments as well).

Michael’s intro paragraph says “you have better options for embedding video and audio content into a web page” than Flash or Silverlight.  Really?  Is this the wondrous HTML5 you speak of?  That isn’t complete, only supported in certain versions of browsers and requires likely a different encoding of the media than you already have?  Yeah, thought so.  Let’s be honest.  Flash and Silverlight are *the* ways to leverage media in mainstream applications today.  Are there alternatives?  Sure.  Are they more pervasive?  No.  On to the article after this little intro correction now.

1. Platform compatibility. 

MYTH: Michael notes the platform where we are supported and on Mac says “only just recently too.” 
FACT: Silverlight has been supported on Mac platforms since it’s incarnation.  The current managed code versions are supported on Intel-based Macs only.  A simple check of the system requirements would have found this.

In the comments Michael states that what he meant by this is that .NET is required.  We’ll get to that in point 9.

MYTH: Windows servers are required for Silverlight.
FACT: You could serve up Silverlight from your Samba share if you want.  Silverlight is a client technology…we don’t care what is on the server.  The only thing we require (for security) is that the XAP must be served with the right content MIME type (application/x-silverlight-app).  That’s it.  And every web server out there can have this MIME type.

2. Market penetration.

Our latest install statistics we see from our downloads, etc. as announced at MIX09 put us around 1/3 market penetration.  This is continuing to grow.  I honestly don’t have daily visibility to this number to give you current stats.  Michael makes a note “Not sure about that, as some independent studies show it as low as 6%” – um, cite the study?  If not, that’s a blatant assumption.  Heck even the much disputed riastats.com shows penetration at 34%.  Again, cite the source, or move along.  I even cite riastats.com here, although that’s not the benchmark that Microsoft uses…but at least I’m citing where I pull the number from (the 34% number, not the 1/3).

3. 64-bit web browser support. 

It’s funny that in the comments Michael says to a commenter not to talk about beta technologies, yet in this point here that’s all the evidence he has: An alpha of Flash for 64-bit.  Silverlight doesn’t have a 64-bit plugin.  Neither does Flash.  Enough said.

4. Supported image formats.

I couldn’t find a definitive source on what image formats Flash officially supports with no extensibility, but I think it is JPG, PNG and GIF (someone cite a source if you have better data).  True, Silverlight doesn’t support GIF.  I’m not upset about it.  Guess what though…we have an extensible platform and if you absolutely need to support your GIFs from 1997, you can.

5. Package Delivery.

MYTH: Silverlight files are loose and uncompressed.
FACT: Silverlight files are packaged into a XAP file which is a standard compressed/archive format.

In fact, just rename to .zip and use your favorite tool to see the contents.  If you think your favorite tool can get even better compression…feel free to recompress again.  We think we have decent improved compression. 

Oh and we also support cached assemblies, partitioning applications, and other techniques to minimize the size of your application base file.  This point tells me he’s evaluating on Silverlight 1.0 (which didn’t leverage the XAP package and was in fact loose files – which could be gzip/deflate compressed by the server btw).

6. Audio.

MYTH: Silverlight does not support APIs for generating and controlling audio.
FACT: Silverlight has a MediaElement control for controlling audio/video, MediaStreamSource API for providing your own decode/logic and APIs for RAW audio, video stream. 

Again, do your research.  Samples available for this here (extensible media format support sample) and here.

7.  Portability.

I’m not sure his description of Flash’s abilities here are even accurate.  I *think* he may be talking about just running a SWF file using the standalone Flash player, but I wonder if he also means AIR here as well.  I’m just not sure (and he doesn’t indicate).  Silverlight has the capability to run out-of-browser.  Is it a full-trust application like AIR?  No.  But again, he doesn’t clarify here what he’s referring to.  Sure Flash has a standalone player, but I can’t remember the last time I played only a SWF.  If referring to AIR, there are some comparisons that could be drawn, but bottom line is you can run Silverlight applications out of the browser.

8.  Accessibility.

MYTH: Silverlight is not an accessible technology.
FACT: Silverlight can be developed with accessibility in mind.

Michael points out “changing color schemes” and I think is referring to high-contrast mode.  Yes we have that.  But we also have caption support for media files and have the ability to integrate with other accessible technologies.  Here’s some resources:

  • Accessible Media Project (full open source implementation of an accessible media player).  Note: that this is built upon *existing* APIs that are built-in to the product.
  • Accessibility in Silverlight with Mark Rideout here and here.
  • Buttercup Reader – an implementation of an accessible application in Silverlight.

9.  Client-server communication.

MYTH: You must use .NET server technologies for service communication on Silverlight.
FACT: Silverlight can communicate with ASP.NET web services, WCF, SOAP services and REST APIs. ASP.NET on the server is not required for client-server communication.

Michael’s assertion here is simply incorrect.  Silverlight has a network stack available to developers to communicate with servers/services of all kinds and also includes a Socket implementation if you so desire.  This is just completely false what Michael notes here.

There are some technologies we are developing (.NET RIA Services) that do require .NET on the server and provide a better experience for developers using Microsoft technologies front-to-back.  This, however, is not a requirement of Silverlight.  Use your Ruby REST api if you’d like.

10.  3D rendering.

I’m definitely not an expert in 3D.  I have to admit I don’t know the capabilities of Flash in this regard.  Silverlight does, however, support perspective 3D (taking a 2D object and putting it in 3D space).  Do we have full on support for 3D meshes, etc.  No, we don’t right now.  I *think* (again, Flashers correct me if I’m wrong) that Flash’s implementation is similar based on some quick search research.  I’m willing to admit I’m wrong here on their implementation.

We do have several ways to extend 3D type models though:

  • Kit3D – an open source 3D graphics engine for Silverlight.
  • Balder – a managed game engine with 2D and 3D support.
  • Zam3D – a commercial product for exporting 3D environments to XAML

As for game development.  Sigh.  Yes it can be done.  In fact how about a platform that lets you reuse technology to develop a game for desktop, browser, XBOX and Zune?  Check out Silver Arcade for some casual games that people are developing.  We’ve also got a thriving ecosystem around physics engines that are open source as well!  Casual games not your thing?  How about Quake in Silverlight?

Michael ends his article with these words (emphasis mine):

I have a platform to express my opinions, and they are generally backed up with solid experience or data to justify them. I am not always right, and I welcome anyone who disagrees with my thoughts on Microsoft’s Silverlight to begin that discussion in the comments section.

Michael – you have been engaged in the comment section and haven’t corrected where you are wrong.  Your opinion, this time, is not backed up with solid experience or data.  Period.


This work is licensed under a Creative Commons Attribution By license.

When Silverlight 3 launched, we also published several additional application themes for the navigation and business application (for .NET RIA Services) templates.  I just uploaded two more themes from one of our designers, Corrina, to the Expression Gallery.  There are versions for both navigation application template as well as the .NET RIA Services business application template.

Mediterranean Sun (RIA Services):

Mediterranean Sun theme image

Seeing Sound (RIA Services):

Seeing Sound theme image

Additionally, several fixes were made to the existing templates that some users reported.  I also added .NET RIA Services templates for those that were missing based on requests (Retro, Skyline, Subdued).

I noticed also that others have been uploading themes, behaviors and other goodness to the Expression Gallery, so be sure to check it out!

I have the pleasure of being invited to participate in two Silverlight events coming up soon (one very soon).  These are a part of a “firestarter” event that is intended to get you familiar with certain technologies, in this case Silverlight, rather quickly and gain a better understanding for the overall platform offerings.  I’m excited to have been invited to participate in both the Atlanta and Seattle events.

Silverlight Firestarter Atlanta

The first one will be in Atlanta, Georgia on 22-August!  It’s been quite some time since I’ve been to Atlanta and I’m very happy to be going to hang out with Silverlight developers there.

Atlanta Silverlight firestarter logo

The agenda looks to be a good one if you are in the area.  It is a free event to attend and will be hosted at the Microsoft office in Alpharetta.  Apparently it is already booked full for registration.  You can find out more information about the plans, location, and schedule at the minisite.  Be sure to check out the Bios section to see the star studded experts that will be there!  Wildermuth said that he’d take me to the largest aquarium…I’m hoping that’s not a ploy to get me eaten by some giant whale shark or something.  I’ll settle for BBQ if we can’t make it to the aquarium Shawn!

Silverlight Firestarter Seattle

Well, technically Redmond, but who’s counting :-).  This event on 17-September will be held at the conference center on the Microsoft campus.  Registration is required, so make sure you register now if you plan on attending.

Seattle Silverlight firestarter logo

This is a pretty packed agenda with some great folks, including Scott Guthrie, Brad Abrams, Adam Kinney, Justin Angel and Karl Shifflett.  I’m honored that Scott would open up for me ;-).  Seriously though, this looks like it will be a good time!  Adam posted his vision on how the day will go.  I better start working on those loads!  Again, registration is required, so make sure you go do that now.

Hope to see you at one of these!

One of the features that a lot of developers seem to enjoy is the out-of-browser feature in Silverlight.  This is the feature that allows you to take your Silverlight application and run it like a desktop application (without some of the trust levels right now).  If you aren’t familiar with the feature, take a moment and familiarize yourself with it…here’s some info:

Now that you have some basis of understanding, allow me to share a thought I’ve had.  I’m seeing a few people wanting to force the out-of-browser (OOB) experience.  That is to say, they want their application to be only run in OOB mode. 

NOTE: If you feel you want this, you should understand the limitations in OOB mode.  Namely the HTML bridge features and certain network implications might affect your applications depending on your needs.

Honestly I am not sure I entirely see the value in that (forcing it), so if you have one, please enlighten me (maybe gaming I suppose).  After all, IsolatedStorage is shared between OOB and in-browser Silverlight applications from the same source.  But I digress. 

The Problem

One thing that I’ve seen is folks asking for a method on how they can force the OOB mode in their app.  One of the security features of OOB is that the Install action must be user initiated.  This means it must be from the end-user action…not automated.  So you can’t just send a URL to someone and have it suddenly install the application OOB.  So how would you go about this?

A Solution

Easy, I think.  Here’s the pattern that I think might work.  I’ll note that this is just my opinion of a solution…not the defacto in all situations.  By all means please consider your own scenario needs before blindly adopting.  That being said, I think it might be helpful to explore.  This solution involves leveraging the OOB APIs available to the developer and creating some different views in your application.

Step 1: Create some views

What you’ll need here really is two views (for lack of a better term at this point – if you want to call them controls, that is fine too) in addition to your main application.  I’ve called one Installer and the other Installed.  The purpose of Installer is that this will be the view shown when a user does not have the application installed OOB.  The purpose of Installed is that it will be the view shown when a user does have the OOB application installed *and* is attempting to view the application in-browser.  The third “view,” your application, is what will be rendered when the user views the OOB application.  Put Installer and Installed wherever you’d like in your app.  I created a folder called Views and stuck them there. 

For Installer, you’ll want to put some UI in here for the Installer “badge.”  I highly recommend putting some time into this using Expression Blend to make it all look great and perhaps add any visual states you may want.  Remember, this is your user’s first impression.  This is still a Silverlight application, so go nuts with styling and using controls.  But you don’t need to make these the same size as your application.  For my example, my OOB application is 800x600, but my Installer app is only 300x162.  This Installer control/view will contain your actual install logic.  So somewhere here you need to have a button or something that the user can initiate as an action that you can call the Install method.  A button is easiest and easy to style.  In the Click event all you have to do (in simplest form, of course you’d want to add some error handling) is add the API call to install:

   1: Application.Current.Install();

For Installed, you’ll do the same thing, except make the UI/UX for the experience of letting someone know they already have it installed.  This could be something as simple as a text message, or complete instructions, etc., whatever.  You decide.

When you are done with this step you should have two XAML UserControls: Installer.xaml and Installed.xaml both for their specific purpose.

Step 2: Wire up the application startup logic

What I’ve chosen to do is take control of the App_Startup logic to determine the state.  I felt it would be better here based on the scenario I’m trying to accomplish rather than to load a default UserControl and have to do some funky app logic to swap out the RootVisual.  What I’ve chosen to do is to check the state of the trigger to run and follow some logic:

  • If the app is installed and the user is running in-browser: Show Installed
  • If the app is not installed and the user running in-browser: Show Installer
  • Else: Show App

The logic finds the correct state in a simple if…elseif…else statement and decides which RootVisual to show.  Here’s the complete code:

   1: private void Application_Startup(object sender, StartupEventArgs e)
   2: {
   3:     if ((App.Current.InstallState == InstallState.Installed) && (!App.Current.IsRunningOutOfBrowser))
   4:     {
   5:         this.RootVisual = new Installed();
   6:     }
   7:     else if (!App.Current.IsRunningOutOfBrowser)
   8:     {
   9:         this.RootVisual = new Installer();
  10:     }
  11:     else
  12:     {
  13:         this.RootVisual = new MainPage();
  14:     }
  15: }

Simple, isn’t it?  You can see that the “app” that gets run is the correct starting point given the state.

Step 3: Configure your OOB settings

Visual Studio 2008 adds a dialog feature for you to easily generate the OOB settings.  You can read more about that here and see some screenshots: Silverlight Out-of-browser Settings Dialog.  Once you’ve done this, when you compile your application it enables it for OOB install capabilities.

Step 4: Deploy

That’s really it.  Of course the harder part is your own application :-), but that’s for you to figure out, not me.  In the end you could then embed your application somewhere within a web page.  It will show your Installer if the user doesn’t have it, or remind them it’s already installed if they do.  Here’s a working example based on this pattern (Silverlight 3 required to run this application):

This is just a stub example app, no working functionality in the main application.  The purpose is just to show this pattern.  As you can see, when the application runs, it runs at the desired 800x600 application width that I want for my actual application, game, whatever.  All this while I minimize the impact visually to show the messages of the Installer and the Installed controls.

Summary

This is just a sample pattern that you may want to implement if the need (or desire) is there to force your applications to be run OOB.  Again, OOB in general should be understood before blindly going in and assuming 100% of what you have will run in this mode.  But if it will and this is something you want, you may consider using this pattern to make a smaller visual impact on the installer and providing the end user with a better user experience to get it installed.  Or at least it was an experiment for me.

Hope this helps!