| Comments

This is part 7 in a series on getting started with Silverlight.  To view the index to the series click hereYou can download the completed project files for this sample application in C# or Visual Basic.

In our final stage of this getting started series, we are going to make our application available for installation outside of the browser.  The steps are much simpler than you think.

Create the manifest

Using Visual Studio, right-click on the Silverlight application’s project and choose properties.  You’ll see a dialog box come up – notice the checkbox about Out-of-browser settings:

Application properties

When you click that you’ll be greeted with options to complete:

Out-of-browser settings dialog

These settings are important to provide visual information about your application when installed and running out of the browser.

  • Window Title – what is displayed in the window chrome for the app
  • Width/Height – the starting width and height of your application when launched
  • Shortcut name – the name for the desktop/start menu shortcut
  • Download description – a description of the application
  • Icons – must be PNG and must be included in the project marked as Content

Once you have all those in place your app is enabled for out-of-browser capabilities.  Let’s add an install button for your users in the navigation area in MainPage.xaml in the StackPanel called LinksStackPanel, add this XAML:

   1: <Rectangle x:Name="Divider3" Style="{StaticResource DividerStyle}"/>
   2: <HyperlinkButton x:Name="InstallLink" Style="{StaticResource LinkStyle}" 
   3:                  Content="install" Click="InstallOffline"/>

Now in MainPage.xaml.cs write the function for InstallOffline:

   1: private void InstallOffline(object sender, RoutedEventArgs e)
   2: {
   3:     if (Application.Current.Install())
   4:     {
   5:         InstallLink.Visibility = Visibility.Collapsed;
   6:     }
   7: }

You can see that after we check for a successful install, we hide the install button as it isn’t needed anymore.  What we need to do though is make that more dynamic in that it automatically knows to do that.  Additionally we don’t want the install button to show if the application is launched out-of-browser to begin with.  Luckily we have an API with a few properties that will help us out: InstallState and IsRunningOutOfBrowser.  Let’s make use of both of these.

Detecting InstallState and IsRunningOutOfBrowser

In the MainPage.xaml.cs file, we’re going to add an event handler to detect the change of our installation state of our application as well as a loaded event handler:

   1: public MainPage()
   2: {
   3:     InitializeComponent();
   4:     Loaded += new RoutedEventHandler(MainPage_Loaded);
   5:     Application.Current.InstallStateChanged += new EventHandler(OnInstallStateChanged);
   6: }

In that method we’ll check the various states to determine if our InstallLink should be visible or not (as well as the last divider):

   1: void OnInstallStateChanged(object sender, EventArgs e)
   2: {
   3:     switch (Application.Current.InstallState)
   4:     {
   5:         case InstallState.InstallFailed:
   6:             break;
   7:         case InstallState.Installed:
   8:             ToggleInstallLinks(true);
   9:             break;
  10:         case InstallState.Installing:
  11:             break;
  12:         case InstallState.NotInstalled:
  13:             ToggleInstallLinks(false);
  14:             break;
  15:         default:
  16:             break;
  17:     }
  18: }
  19:  
  20: void ToggleInstallLinks(bool hidden)
  21: {
  22:     InstallLink.Visibility = hidden ? Visibility.Collapsed: Visibility.Visible;
  23:     Link3.Visibility = hidden ? Visibility.Collapsed : Visibility.Visible;
  24: }

Now in the Loaded event handler we’ll check to see if the application is running out-of-browser or not:

   1: void MainPage_Loaded(object sender, RoutedEventArgs e)
   2: {
   3:     if (App.Current.IsRunningOutOfBrowser)
   4:     {
   5:         ToggleInstallLinks(true);
   6:     }
   7:     else
   8:     {
   9:         if (App.Current.InstallState == InstallState.Installed)
  10:         {
  11:             ToggleInstallLinks(true);
  12:         }
  13:     }
  14: }

Using these two APIs we can now automatically change our UI to hide functions not needed.

Detecting network changes

If our application doesn’t have network access, we shouldn’t allow the search to run because it may not have the capability of finding the Twitter search API.  There is an additional API for NetworkInterface that we can use to detect this.  We’ll do this in our Search.xaml.cs page by first adding an event handler in the constructor after our Loaded event handler line:

   1: NetworkChange.NetworkAddressChanged += new NetworkAddressChangedEventHandler(OnNetworkChanged);

This raises an event when the network status has changed.  Now in the OnNetworkChanged event handler we’ll check to see if the network is available and, if it isn’t, disable searching capabilities until it is:

   1: void OnNetworkChanged(object sender, EventArgs e)
   2: {
   3:     if (!NetworkInterface.GetIsNetworkAvailable())
   4:     {
   5:         // network may not be available, halt searching
   6:         SearchButton.IsEnabled = false;
   7:         SearchButton.Content = "DISCONNECTED";
   8:         _timer.Stop();
   9:     }
  10:     else
  11:     {
  12:         SearchButton.Content = "SEARCH";
  13:         SearchButton.IsEnabled = true;
  14:         _timer.Start();
  15:     }
  16: }

This is only an example of course, and you could provide other UI hints such as status indicators, etc. but for our application this should work now.

NOTE (Here be dragons): Simply checking for GetIsNetworkAvailable doesn’t guarantee in all circumstances that the Internet is not available.  Due to various ways corporations configure proxy servers and local IP addressing it is always good practice to have a fallback mechanism if you need to verify WAN Internet access.  This can be done by simply doing a WebClient request for a file on the web server – if the request succeeds you have Internet access, otherwise you may not.

You can find out more information about Out-of-browser experiences here:

Out of browser updates

You may be wondering how to trigger updates to an application if it was installed on to the machine.  There is an API that a developer can use called CheckAndDownloadUpdateAsync which triggers the update model.  The update model is outlined here.  Even though that article has a different API, the model of updating is the same *after* that method above is called.

Summary

Now we’ve taken our application from a blank slate to a working application with data and that can be installed out of the browser.  I hope this has been a helpful exercise to walk through.  Download the code to be sure to play around with it and learn.  Here are some other helpful resources for you:

Hopefully this will get you started writing Silverlight applications!

| Comments

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!