Taking the Silverlight Control Browser sample Out-of-Browser ... plus a tutorial

19 November 2009

We’ve enabled Out of Browser support for the Silverlight Control Browser application for the Silverlight Toolkit. That was reason enough for me to blog a little bit about that, and offer an overall guide to how to hook up to the proper events and respond to install state changes. Near the end of the post, I’ve even come up with a more attractive update notification that I hope I can move the samples app to in the future – message boxes are so n – 14 years ago.

The Silverlight Control Browser is a one-stop resource for learning about the core controls in Silverlight, the controls in the Silverlight SDK (like DataGrid), and of course the value-add controls and features that are found in the extra Silverlight Toolkit download.

By installing the app on your machine, you can learn about the controls even when offline. Perfect for those long holiday flights that are coming up this next month, when your airline doesn’t provide wireless Internet. (Aside: I recently flew Delta and the wireless in-flight Internet rocked. Big time. I’ve never had a flight home to Seattle go by so quickly)

Another scenario: the infamous hipster coffee shops in Seattle whose wifi routers go down and never come up again. This morning I was in such a coffee shop without Internet, but was still able to fire up the sample app and grab a screen shot for the new BusyIndicator control that’s in the Silverlight Toolkit now.

BusyIndicatorSample 

Any interest in an Out of Browser Helper Control?

One thing I’ve been wondering if whether an ‘OutOfBrowserHelper’ control would be a useful, and quick, control for us to turn around inside the Silverlight Toolkit: something that has a very small scope, specific purpose, and will save developers time.

I’m imaging that this would wrap up the update logic, potentially offer the Install button, and other core services. I don’t know how practical it is, but I’d be interested in thoughts out there. Later in this post I talk about what all you need to do to enable the right Out of Browser update pattern in your apps.

I’ve created a Wishlist Feature request on the Silverlight Toolkit issue tracker to see if anyone else thinks it would be interesting…

A well-designed app that looks great in the browser looks great outside of it, too. What I like most about the Silverlight Out of Browser feature, compared to others, is that you don’t need to install anything else: no special runtime, no User Account Control permission, etc – since those apps run in the same security sandbox that Silverlight apps do while hosted in the Silverlight plugin.

This post is specific to that nice, simple Out of Browser support in Silverlight 3. For the hardcode developers out there, and some very interesting scenarios, Silverlight 4 adds a special elevated trust mode. That mode is outside the scope of this post.

OutOfBrowser

Enabling Out of Browser for your own applications

A key feature in Silverlight 3, it takes about half an hour to enable Out of Browser if you’re a developer and looking to create your own graphics for the experience. Your users will notice that you have no design talent, but that is half the fun. Also, this is why “battleship gray” is so prevalent in Windows today.

If you have graphic assets from your designers, you can add the feature in about 2 minutes.

Here’s the technical set of hoops you need to do to define the Out of Browser metadata for your app.

Using Visual Studio 2008 or Visual Studio 2010 Beta 2

  • First off, once you have the Silverlight Tools installed, just right-click on the project file in the Solution Explorer.
  • Then, navigate to the Silvelright tab.
  • Check the ‘Enable running application out of the browser’ option. This option will not be available if the ‘Reduce XAP size by using application library caching’ option is checked, fyi.
  • Click the ‘Out-of-Browser Settings’ button.

VisualStudioOutOfBrowser

This window will then allow you to set the Out of Browser information, such as a nice quick blurb about the app, the application title, and other basics. This data is all stored in the .\Properties\OutOfBrowserSettings.xml in your project directory structure.

You’ll need to have those icons ready at this point.

OutOfBrowserSettings

Click OK, and that is it: your application can now be taken out of the browser!

OutOfBrowserSettings.xml

This file should be placed inside your Properties folder of the Silverlight application project. Visual Studio will create it for you when you enable the experience, and in fact the Silverlight Tools even offer tooling to easily modify these properties. If you author it by hand, the file is of build type ‘None’, and hooked up inside the .csproj or VB project through these properties:

    <EnableOutOfBrowser>true</EnableOutOfBrowser>

    <OutOfBrowserSettingsFile>Properties\OutOfBrowserSettings.xml</OutOfBrowserSettingsFile>

Here’s what it looks like for the Silverlight Toolkit. We’ve defined the expected 16x16, 32x32, 48x48, and 128x128 brand icons. The icons are included in the project and marked as ‘Content’ in the Visual Studio properties dialog, so that they are in the Xap at the end of the build process.

<OutOfBrowserSettings ShortName="Silverlight Controls Browser" EnableGPUAcceleration="True" ShowInstallMenuItem="True">

  <OutOfBrowserSettings.Blurb>Sample explorer for the controls and features found in the Silverlight Toolkit and Silverlight SDK.</OutOfBrowserSettings.Blurb>

  <OutOfBrowserSettings.WindowSettings>

    <WindowSettings Title="Silverlight Controls Browser" />

  </OutOfBrowserSettings.WindowSettings>

  <OutOfBrowserSettings.Icons>

    <Icon Size="16,16">Toolkit16.png</Icon>

    <Icon Size="32,32">Toolkit32.png</Icon>

    <Icon Size="48,48">Toolkit48.png</Icon>

    <Icon Size="128,128">Toolkit128.png</Icon>

  </OutOfBrowserSettings.Icons>

</OutOfBrowserSettings>

Other options

There are several additional Out of Browser options to chose from. The Silverlight 4 Beta also adds the elevated trust option here.

Use GPU Acceleration: Check this to enable acceleration if your application will benefit from this.

Show install menu: By default selected, this adds the option to Install the app (and take it Out of Browser) to the right-click menu for your Silverlight application.

If you decide not to show the install menu, you’ll need to implement your own user interface to show an Install button or other experience.

The one included in the Silverlight Toolkit sample app is a good example – implemented in Welcome.xaml and Welcome.xaml.cs, it is aware of the state of the running application and whether to offer the install option or not.  

Implementing all the necessary things to make Out of Browser shine

Tim Heuer offers important information about making the Out of Browser experience world-class. For instance, you need to actually have you app asynchronously check for updates, and offer information about the availability of any updates.

  • You need to call CheckAndDownloadAsync and react to that in your user interface
  • You should check the InstallState if you want to offer different user interfaces depending on the Out of Browser state

Tim also has a recommended pattern for effectively forcing an app to only be available Out of Browser, similar to the experience you might find with other popular apps that live outside of the browser.

Here’s the App.xaml.cs file from the Silverlight Toolkit controls sample browser, to give you an idea of what we do. We’re only showing a MessageBox when an update becomes available, but you can make the experience a little richer if needed (see father down the post for that).

// (c) Copyright Microsoft Corporation.

// This source is subject to the Microsoft Public License (Ms-PL).

// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.

// All other rights reserved.



using System;

using System.Windows;

using System.Collections.Generic;

using System.Linq;



namespace System.Windows.Controls.Samples

{

    /// <summary>

    /// System.Windows.Controls samples application.

    /// </summary>

    public partial class App : Application

    {

        /// <summary>

        /// Initializes a new instance of the App class.

        /// </summary>

        public App()

        {

            if (App.Current.InstallState == InstallState.Installed)

            {

                App.Current.CheckAndDownloadUpdateCompleted += OnCheckAndDownloadUpdateCompleted;

                App.Current.CheckAndDownloadUpdateAsync();

            }



            Startup += delegate

            {

                RootVisual = new SampleBrowser(SampleTreeItems);

            };

            InitializeComponent();

        }



        /// <summary>

        /// Checks for the update completed event.

        /// </summary>

        /// <param name="sender">The source object.</param>

        /// <param name="e">The event arguments.</param>

        private void OnCheckAndDownloadUpdateCompleted(object sender, CheckAndDownloadUpdateCompletedEventArgs e)

        {

            if (e.UpdateAvailable)

            {

                MessageBox.Show("An application update has been downloaded and "

                              + "will be available the next time you start the "

                              + "sample application.");

            }

            else if (e.Error != null)

            {

                MessageBox.Show("While checking for an application update, the "

                              + "following message was encountered:"

                              + Environment.NewLine 

                              + Environment.NewLine 

                              + e.Error.Message);

            }

        }

    }

}

Offering a button experience for taking the app Out of Browser

Although you could just offer the experience in the right-click context menu of your Silverlight app in the browser, that’s not a very well-advertised and visual feature. For the samples app, we expose a button to “Install” the app on the machine.

We want to be able to update that offering UI in real-time, so once the user takes the app out of browser, the Install button is no longer visible.

We do this by subscribing in the Welcome.xaml.cs page to the OnInstallStateChanged event of the Application:

// Make sure that we are connected to the installation state change

// at least once.

Application.Current.InstallStateChanged += OnInstallStateChanged;

And our Button has an event handler attached to start the actual install. The install call needs to happen in a user-initiated action: you can’t just call it whenever you like, but instead it needs to be placed somewhere in response to the user making a conscious installation decision:

/// <summary>

/// Installs the application.

/// </summary>

/// <param name="sender">The source object.</param>

/// <param name="e">The event arguments.</param>

[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Event connected in XAML.")]

private void InstallSamplesClick(object sender, RoutedEventArgs e)

{

    Application.Current.Install();

}

When they click that button, they’ll see the Consent Experience for the app. The clear and concise consent dialog is powered by Silverlight, but you’re able to customize the graphic displayed with your own designer brand asset:

OutOfBrowserPrompt

And then we are able to react to that by manually changing text, enabled status, visibility, etc. I’m sure a data binding expert would be able to make this example a little more attractive looking, but the code works!

/// <summary>

/// Shows or hides the installation button.

/// </summary>

/// <param name="sender">The source object.</param>

/// <param name="e">The event data.</param>

private void OnInstallStateChanged(object sender, EventArgs e)

{

    switch (App.Current.InstallState)

    {

        case InstallState.Installing:

            InstallButton.Visibility = Visibility.Visible;

            InstallButton.IsEnabled = false;

            InstallButton.Content = "Installing...";

            break;



        case InstallState.Installed:

            InstallButton.Visibility = Visibility.Collapsed;

            InstallText.Text = "The samples have been installed on this computer.";

            break;



        case InstallState.NotInstalled:

            InstallButton.Visibility = Visibility.Visible;

            InstallButton.IsEnabled = true;

            break;



        case InstallState.InstallFailed:

            InstallButton.Visibility = Visibility.Collapsed;

            InstallText.Text = "The Out of Browser installation failed.";

            break;

    }



    InstallApplicationPanel.Visibility = App.Current.IsRunningOutOfBrowser ? Visibility.Collapsed : Visibility.Visible;

}

A smoother notification method

Since most users aren’t going to immediately want to close the app they are working with, when an update becomes available, you’ll realize that the MessageBox.Show(…) route for the notification is jarring and rather inappropriate.

If you instead embed that information inside of your user interface, it can be simple “FYI” that is not as abrupt.

Here’s a simple use: if your root visual for the app contains a DockPanel, you could have a collapsed user interface element for displaying important messages, such as the availablility of an update.

Here’s what my UI might look like when a new version is available:

UpdateNotification

This user interface is accomplished with the toolkit’s DockPanel control, plus a little code behind. Here is the main application XAML:

<controlsToolkit:DockPanel Background="White">

    <!-- Out of Browser Notification -->

    <Border Height="32" 

            BorderBrush="#b4a555" 

            BorderThickness="1"

            x:Name="OutOfBrowserNotification"

            Visibility="Collapsed"

            controlsToolkit:DockPanel.Dock="Top">

        <Grid>

            <Grid.Background>

                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">

                    <GradientStop Color="#fff6bd" Offset="0" />

                    <GradientStop Color="#ffec82" Offset="1" />

                </LinearGradientBrush>

            </Grid.Background>

            <Grid.ColumnDefinitions>

                <ColumnDefinition />

                <ColumnDefinition Width="24" />

            </Grid.ColumnDefinitions>

            <StackPanel Orientation="Horizontal">

                <TextBlock FontWeight="Bold" 

                           VerticalAlignment="Center"

                           Text="Update Notification:" 

                           Margin="5" />

                <TextBlock VerticalAlignment="Center">The next time you use 

                    this app, you'll be on the hot new version.

                </TextBlock>

            </StackPanel>

            <TextBlock Grid.Column="1"

                       HorizontalAlignment="Center"

                       VerticalAlignment="Center"

                       FontWeight="Bold"

                       Text="X"

                       Padding="6"

                       MouseLeftButtonDown="OnCloseUpdateNotification"

                       />

        </Grid>

    </Border>

    

    <Grid x:Name="LayoutRoot">

        <Button Content="Your Application Goes Here" 

                Opacity=".4"/>

    </Grid>

</controlsToolkit:DockPanel>

So, except when an update is available, the top notification section would not even be taking up any space. So here’s the code that responds to the application’s CheckAndDownloadUpdateCompleted event:

private void OnCheckAndDownloadUpdateCompleted(object sender, CheckAndDownloadUpdateCompletedEventArgs e)

{

    if (e != null && e.UpdateAvailable)

    {

        OutOfBrowserNotification.Visibility = System.Windows.Visibility.Visible;

    }

}

Behind the scenes, I’ve wired up a fake close button, so users can dismiss the window at their leisure:

private void OnCloseUpdateNotification(object sender, MouseButtonEventArgs e)

{

    OutOfBrowserNotification.Visibility = System.Windows.Visibility.Collapsed;

}

For more information about the Silverlight Out of Browser feature, please check out the official MSDN Library documentation, “Out-of-Browser Support”.

Out of Browser and Application Library Caching: Mutually Exclusive

You may have also read that we’re finally shipping the application library cache support files in the November 2009 release of the Silverlight Toolkit. Unfortunately, we haven’t enabled library cache support for the samples application, because we feel the value provided by Out of Browser trumps the cached library scenario.

When you setup Out of Browser support, you cannot enable Application Library Caching. The Visual Studio project properties are good about enforcing this.

The reason is that the Out of Browser experience requires that the entire Xap be self-contained, and when you enable application library caching for a project, it drops a bunch of .Zip files (zipped up versions of those dependent libraries) alongside the main app’s .Xap file. When Out of Browser, you may not always be able to download or grab those files.

Consider a Splash Screen if you have a large app that is Out-of-Browser enabled

I created a custom splash screen experience for the controls sample app that is hosted up on Silverlight.net, since the application is several megs. Your grandmother’s probably not interested in the control browser app, so don’t worry about those 14.4k modem users. My grandmother isn’t even interested, and she knows I work on this stuff!

The splash screen for the Silverlight Toolkit consists of a Silverlight Toolkit brand logo, a ton of TextBlocks, and I’m also using the native Grid to center the entire experience within the plugin. There’s a little JavaScript to update the text block with the percents, and the rest of the cycling animation is powered by several Storyboards that start when the page is initally loaded.

This is a good alternative to application library caching in some situations. Do remember to keep the splash screen small – users are much more interested in your app. Hopefully.

Download the Silverlight Toolkit November 2009 Release Today

Toolkit32

The Silverlight Toolkit is a collection of Silverlight controls, components and utilities that help make Silverlight development a little easier, more fun, and add value outside the regular Silverlight release cycle.

The sixth release of the Silverlight Toolkit, the November 2009 release targets Silverlight 3. There is also a release available that targets the new Silverlight 4 Beta for developers.

Resources of note:

Hope you enjoy our new release!

Jeff Wilcox is a Software Engineer at Microsoft in the Open Source Programs Office (OSPO), helping Microsoft engineers use, contribute to and release open source at scale.

comments powered by Disqus