Silverlight: Unhandled Exception and MVVM Light

Standard

The MVVM Light Toolkit is one of the most popular MVVM framework that Silverlight developers are using. While it’s very handy for data binding and manipulation, you have to beware that there’s a little difference to handle unhandled exceptions.

Usually you would expect all unhandled exceptions would end up in the automatically generated Application_UnhandledException event handler in yoru App.xaml.cs file. A lot of developers would create their custom exception class and catch all exceptions in this event handler as a centralized place to process the exceptions and perform appropriate actions accordingly. But, when you try to raise an exception in, say, a property in one of your MVVM Light view model, this may not always be the case.

For example, in my main view model, I have a simple property:

private int _price;
public int Price
{
    get { return _price; }
    set
    {
        if (value < 0) throw new MyException("Price cannot be less than 0.");
        _price = value;
        RaisePropertyChanged("Price");
    }
}

Then in the Application_UnhandledException event handler, I wanted to show the exception message to the users:

private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
{
    if (e.ExceptionObject is MyException)
    {
        // Show all MyException's message to the user.
        e.Handled = true;
        MessageBox.Show(e.ExceptionObject.Message);
    }
    else
    {
        // Handle other exceptions here.
    }
}

This looks good enough except one problem, the exception will never end up in the Application_UnhandledException event handler. This is because in the MVVM Light view model locator (by default the ViewModelLocator.cs file), uses a static reference of your main model to bind data to your UI components. static reference is probably running in a different system thread then your instantiated UI components. So when you raise your exception in your view model, the exception won’t reach any event handlers that are in a different thread.

The solution to this problem is rather simple: you raise the exception in the same UI thread.

private int _price;
public int Price
{
    get { return _price; }
    set
    {
        if (value < 0)
        {
            // Throw the exception in the UI thread.
            App.Current.RootVisual.Dispatcher.BeginInvoke(() => { throw new MyException("Price cannot be less than 0."); });
            // Prevent the property from being set to the incorrect value.
            return;
        }
        _price = value;
        RaisePropertyChanged("Price");
    }
}

The modified property uses the Dispatcher object of the current application’s RootVisual, which is usually your Main Page. The BegainInvoke function will throw the exception in the same thread of the RootVisual, which would be the same thread as your application. Thus making the exception catchable in the application’s Application_UnhandledException event handler.

Note that BeginInvoke executes the action in another thread. This is an asynchronous operation that does not interrupt your current execution. So you usually need to put in the extra “return;” statement to manually interrupt the execution if you need to. This is not necessary in a normal case since raising an unhandled exception only interrupts the execution process in it’s own thread.

Note: Catching exceptions in Application_UnhandledException may raise performance concern. If you are a Windows Phone 7 developer, you should test your exception catching performance on a real device. In most cases, this will cause perceivable slowness and is usually not a recommended approach.

About these ads

3 thoughts on “Silverlight: Unhandled Exception and MVVM Light

  1. And above all, follow your mother’s advice and “don’t put anything smaller than your
    elbow into your ear”. In the event the noise in your ears is caused by this the best method of relief you have is to address your mental or emotional issues. Ringing in the ears or tinnitus can be prevented by changing a few things about the way you live.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s