Task-It Series

This post is part of a series of blog posts and videos about the Task-It (task management) application that I have been building with Silverlight 4 and Telerik's RadControls for Silverlight 4. For a full index of these resources, please go here. One of the posts listed in the index provides a full source download for the application, and I will be referring to that source code in this post.

Prior topics

In my last 2 event-related posts I talked about passing information between components via events and using events in providing feedback to a user when time consuming operations are in progress. I also blogged recently about handling data load (and data save) errors. If you have not read those posts yet, I recommend going to the Task-It index (see link above) and reading those posts first. These lay the base for what I am going to talk about in this post.

Trapping the error

We saw in the handling data load errors post how when the LoadOperation is complete (the call to the server asking for data...in this case a list of tasks), we first check to see if it has any errors.

void OnTasksLoaded(LoadOperation<Task> lo)
{
    if (lo.HasError)
    {
        Utils.ShowErrorMessage(TasksErrorStrings.Message_LoadingTasksFailed, lo.Error.Message);
        lo.MarkErrorAsHandled();
        return;
    }
  
    this.OnPropertyChanged(p => p.Tasks);
    this.OnPropertyChanged(p => p.CalendarTasks);
    HasTasks = Tasks.Count() > 0;
    Utils.HideBusyIndicator();
}

So let's assume that an error has occurred. The first thing that will happen is that we call a utility method that will take in the information passed as parameters and fire and event, the second thing is that we will mark the error as 'handled'. Note that the first argument as a string from a resx (string resource) file. This is so that our error message can be 'internationalized', or 'localized', or whatever you want to call it. Put it this way we can present it in other languages. :-) 

Publishing the event

Now let's take a look at the utility method, which lives in the Core folder under the Task-It project.

public static void ShowErrorMessage(string errorMessage, string operationErrorMessage)
{
    var args = new OperationErrorArgs(errorMessage, operationErrorMessage);
    Messenger.Default.Send(args);
}

Yes, it only has two lines of code, but I'd rather have single lines that call this utility method throughout my code, rather than repeating these 2 lines every time.

So we new up an instance of OperationErrorArgs, passing our error information, and then fire the event using the same Messenger class used in the last two event posts. OperationErrorArgs is very simple. It simply stores the error strings in two properties.

public class OperationErrorArgs
{
    public OperationErrorArgs(string errorMessage, string operationErrorMessage)
    {
        ErrorMessage = errorMessage;
        OperationErrorMessage = operationErrorMessage;
    }
 
    public string ErrorMessage { get; set; }
    public string OperationErrorMessage { get; set; }
}

Listening for the event

So now that we have fired the event, let's take a look at where we listen for it. Just a reminder that what makes this event unique from the many other events in the app is the argument object that is being passed. So to listen, I have the following line in the constructor of MainPageViewModel, in the ViewModels folder under the Task-It project.

public MainPageViewModel()
{
    ...
    Messenger.Default.Register<OperationErrorArgs>(this, OnOperationError);
    ...
}

Now let's look at the method that is called when the event is fired, OnOperationError.

public void OnOperationError(OperationErrorArgs args)
{
    ErrorMessage = Utils.GetErrorMessage(args);
    NotifyError();
}

The first line calls a utility method that basically just joins the 'user friendly' message we pulled from our resx file with the error message that came back from the LoadOperation. The result is stored in a property in the view model called ErrorMessage. Then we call NotifyError, which simply fires the Error event that notifies our user control that an error has occurred.

In the code-behind of MainPage.xaml, in the Task-It project, we naturally listen for that event and call the OnError method.

ViewModel.Error += OnError;

This method simply shows our RadWindow that lives in the XAML.

void OnError(object sender, RoutedEventArgs e)
{
    ErrorWindow.ShowDialog();
}

Lastly, let's look at the RadWindow in MainPage.xaml.

<telerikNavigation:RadWindow x:Name="ErrorWindow" Header="{Binding ResourceTitleError}">
    <StackPanel>
        <TextBlock Text="{Binding ErrorMessage}" MaxWidth="600" TextWrapping="Wrap"/>
        <Rectangle Style="{StaticResource StandardSpacerStyle}"/>
        <StackPanel Orientation="Horizontal">
            <Button Content="{Binding ResourceCommandClose}" Command="{Binding CloseErrorWindowCommand}" TabIndex="0"/>
        </StackPanel>
    </StackPanel>
</telerikNavigation:RadWindow>

Notice that it has a TextBox that is bound to the ErrorMessage property in our view model.

Wrap up

So we saw that when an error occurs, we use a utility method to send an event with an argument object that contains our 'user-friendly' error message. The view model for our main page listens for the event, stores the error message in a member variable, sends an event to MainPage to inform it that an error occurred, and the listener for that event displays the ErrorWindow.


Related Posts

Comments

Comments are disabled in preview mode.