(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .

Application Events in Silverlight

(8 votes)
Gill Cleeren
>
Gill Cleeren
Joined Apr 02, 2010
Articles:   51
Comments:   5
More Articles
1 comments   /   posted on Apr 26, 2011
Tags:   events , gill-cleeren
Categories:   General

During the lifetime of a Silverlight application, some application-wide events are triggered automatically. While they are important from the perspective of Silverlight, they can come in handy as well for us as application developers: they can be seen as a hook in the application execution to which we can attach and execute custom code upon being triggered.

There are 3 events that have a high importance. The Application.Startup event fires when the application is initiating. It needs no explanation that we can use this event to perform initialization tasks. In fact, Silverlight’s default application template generates code in this event that is required for application setup. We’ll see later what we can do in this event and how it gets triggered. A second event is the UnhandledException event. As the word implies, this event gets triggered when an exception occurs in our code that we haven’t caught using a try/catch statement. We’ll see that this event can be seen as a last resort to try saving your application from crashing. Finally, the third event is the Application.Exit event. This event gets called when your application is shutting down, no matter what caused it to close. Even if something went terribly wrong in your code, this event still gets triggered. We’ll soon see that this event can easily be used for example to save important application data. Since Silverlight’s birth, these events can all be found in the App.xaml.cs.

In this article, we’ll take a look at these events in some detail and we’ll see how we can practically use them in our applications to make the latter more robust. The code for this article can be downloaded here.

First things first: let’s start by looking how these events get wired up inside any application.

Wiring up the events

Every Silverlight application has inside its XAP file a manifest file called AppManifest.xaml. The code for this gets generated automatically and gets read out when the application is executed.

 
<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment" 
xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml 
EntryPointAssembly="ApplicationEvents" 
EntryPointType="ApplicationEvents.App" RuntimeVersion="4.0.50826.0">
<Deployment.Parts>
<AssemblyPart x:Name="ApplicationEvents" Source="ApplicationEvents.dll" 
/>
</Deployment.Parts>
</Deployment>

 

Note in the above code the EntryPointType: it refers to the App class inside the application. If you would for any reason change this to be another class, you could do so. However, in most cases, this is not needed. The important thing is that by reading out the manifest file, Silverlight knows which class contains the application startup code.

In the App.xaml.cs, the App class resides. This class has the following constructor:

 
public partial class App : Application
{
    public App()
    {
        this.Startup += this.Application_Startup;
        this.Exit += this.Application_Exit;
        this.UnhandledException += this.Application_UnhandledException;
        InitializeComponent();
    }
...

 

In the constructor, 3 application-wide events are being wired-up: Startup, Exit and UnhandledException. So, without us having to do anything, our events are ready!

Let’s know look at the Startup event and how we can put it to good use.

Get going with the Application.Startup

Because of the wiring in the constructor, the Application_Startup method gets called when the application is starting. By default, the following code gets generated.

private void Application_Startup(object sender, StartupEventArgs e)
{
    this.RootVisual = new MainPage();
}

 

Silverlight sets the RootVisual as an instance of MainPage. This can never be changed anymore: once the RootVisual is set, it cannot be removed or changed into another control. If you however would want to do so, a possible solution is placing a Grid or “template user control” as the RootVisual. Using a public method, you could then change the content of the Grid.

In the Startup event, we have access to parameters being passed to the Silverlight application. In fact, the Startup event is the only place in the application where we have access to these, so if we want to capture them, we have to do so right here. The following code shows how we can capture a parameter (note that it’s very well possible that the parameters aren’t there so we have to check for this):

public string Color { get; set; }
 
private void Application_Startup(object sender, StartupEventArgs e)
{
    if (e.InitParams.ContainsKey("Color"))
    Color = e.InitParams["Color"];
    this.RootVisual = new MainPage();
}

 

The Startup event can also be used to “restore” the previous application state. Assume that we store a value in isolated storage or isolated storage settings. In the startup event, we can check if this value is available or not and act accordingly. The following code checks if a user was logged in and if so, load MainPage instead of LoginPage.

private void Application_Startup(object sender, StartupEventArgs e)
{
    if (IsolatedStorageSettings.ApplicationSettings.Contains("UserName"))
        this.RootVisual = new MainPage();
    else
        this.RootVisual = new LoginPage();
}

 

Finally, we could perform logging actions in this startup event. Assume we have a logging service that wants to be notified about the application being executed. We could call this service in the startup event like so:

 
private void Application_Startup(object sender, StartupEventArgs e)
{
    LoggingService.LoggingServiceClient client = new 
    LoggingService.LoggingServiceClient();
    client.LogCompleted += new 
    EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(client_LogCompleted);
    client.LogAsync(DateTime.Now.ToLongDateString());
}
 
void client_LogCompleted(object sender, 
    System.ComponentModel.AsyncCompletedEventArgs e)
{
    //nothing needed here
}

 

Whenever the application is executed, a log entry is created.

Handling all exceptions in one place

Although we all hope nothing ever goes wrong inside of our applications, errors will occur. A service that can’t be contacted, an IO error, invalid input from the user… all things that CAN and WILL go wrong at some point during the lifetime of an application.

We should write our code so that it’s armed against these possible errors. Managed error handling is exactly the same in Silverlight than in regular .NET, so the use of a try/catch statement is advised around code that is dependent on external factors.

But even if we apply this, something could still go wrong. For this, the Application.UnhandledException event handler exists. This event handler gets called whenever something goes wrong in our code that we haven’t caught. Sometimes, developers rely on this event handler to do all their error handling: they don’t catch an exception but let it bubble up all the way to the UnhandledException and there they handle all errors in the same way (for example by notifying the user and logging the error to a service). While this is an easy approach to managing exceptions, I don’t believe it to be a good practice: I like being in control more when something goes wrong in my code and handle the exception gracefully where it occurs (based on the type of exception, I can handle the exception differently).

Nevertheless, the Application.UnhandledException is very useful. We can mark an error to be handled, thus causing the application not to crash whatever the exception. In the code below, we handle a DivideByZeroException by showing a message to the user and setting the e.Handled = true. The latter results in the fact that the application will keep running despite the exception.

 
throw new DivideByZeroException();
...
 
private void Application_UnhandledException(object sender, 
ApplicationUnhandledExceptionEventArgs e)
{
    if (e.ExceptionObject is DivideByZeroException)
    {
        MessageBox.Show("Darn it, you divided by zero, now ths sky is falling");
        e.Handled = true;
    }
}

 

Note the instance of the ApplicationUnhandledExceptionEventArgs that gets passed: it refers to the exception causing us to arrive in the event handler in the first place.

Now that we know how the UnhandledException gets called whenever an error occurs that we aren’t catching, let’s finish by looking at what we can use the Exit event for.

Going out in style using the Application.Exit event

Just like the Startup gets called automatically when the app is starting, the Exit event gets called when the application shuts down. This code will get executed no matter what: even if an error occurs causing the application to hit the UnhandledException, the Exit event will still be raised. This event is therefore the ideal place to save data. A good example is storing data that is read out with the next run of the application.

In the code below, we store a value in application settings. We can be sure this value gets stored, since the code is in the event handler of the Exit event.

 
private void Application_Exit(object sender, EventArgs e)
{
    IsolatedStorageSettings.ApplicationSettings["UserName"] = "Gill Cleeren";
    IsolatedStorageSettings.ApplicationSettings.Save();
}

 

Another example of where this event might be useful is the following: assume the user has entered a lot of data on a screen. Being good developers, we would like to offer the best experience to our users. Therefore, we would capture that data and store it using code in the Exit event handler, in case the application fails for some reason. Also, logging code can be written here as well, making sure that we know when the user exits the application.

Summary

In this article, we look at the 3 most important application-wide events in a Silverlight application: Startup, UnhandledException and Exit. We pointed out that these events can be interesting to create a better experience for the user by automatically saving state information for the user so that in a next session, the user can continue where he left of.

About Gill

Gill Cleeren is Microsoft Regional Director (www.theregion.com), Silverlight MVP (former ASP.NET MVP), INETA speaker bureau member and Silverlight Insider. He lives in Belgium where he works as .NET architect at Ordina. Passionate about .NET, he’s always playing with the newest bits. In his role as Regional Director, Gill has given many sessions, webcasts and trainings on new as well as existing technologies, such as Silverlight, ASP.NET and WPF at conferences including TechEd Berlin 2010, TechDays Belgium, DevDays NL, NDC Oslo Norway, SQL Server Saturday Switserland, Spring Conference UK, Silverlight Roadshow in Sweden… He’s also the author of many articles in various developer magazines and for SilverlightShow.net. He organizes the yearly Community Day event in Belgium.

He also leads Visug (www.visug.be), the largest .NET user group in Belgium. Gill recently published his first book: “Silverlight 4 Data and Services Cookbook” (Packt Publishing). You can find his blog at www.snowball.be.

Twitter: @gillcleeren


Subscribe

Comments

  • -_-

    RE: Application Events in Silverlight


    posted by Denis Vuyka on Apr 26, 2011 22:08
    The biggest issue Silverlight 4 has is that it is impossible to make web calls during Application.Exit. It is fine that you can access IsolatedStorage upon exit but most of the business scenarios require accessing servers to update database or trigger performing some "logout" tasks, even storing settings remotely not to be bound to local isolated storage on a single machine. Neither WCF nor HTTP calls are allowed and this is one of the troubles LOBs have these days. I really hope this will be fixed for Silverlight 5.

Add Comment

Login to comment:
  *      *