To
modify the WeatherRx application, you will first add buttons to the UI
to allow the user to either retry the failed connection or to exit
gracefully. Then, you will add code to the application to react to the
events on these new User Interface elements.
To add the new elements to the WeatherRx UI, do the following:
pen MainPage.xaml and add two buttons right below the lblStatus textblock, as shown in Figure 1. Name the first button btnRetry and set its Content property to "Retry." Name the second button btnQuit and set its Content property to "Quit." Set the Visibility of both buttons to Collapsed.
On retry, you will recreate the Observable connection to the weather web service, if it's needed, and then invoke the web service again.
Double-click the "Retry" button and add the following handler code to the btnRetry_Click function:
private void btnRetry_Click(object sender, RoutedEventArgs e)
{
btnQuit.Visibility = System.Windows.Visibility.Collapsed;
btnRetry.Visibility = System.Windows.Visibility.Collapsed;
lblStatus.Text = "";
WireUpWeatherEvents();
weatherClient.GetWeatherByZipCodeAsync(txtZipCode.Text);
}
If the user selects Quit, let's simply hide the buttons and the exception text.
Double-click the "Quit" button and add the following code to the btnQuit_Click function:
private void btnQuit_Click(object sender, RoutedEventArgs e)
{
btnQuit.Visibility = System.Windows.Visibility.Collapsed;
btnRetry.Visibility = System.Windows.Visibility.Collapsed;
lblStatus.Text = "";
}
Finally, you will need to ensure there is only one subscription to the weather web service at any given time.
To ensure that there's only one subscription, first declare a module level variable by adding the following statement:
IObservable<IEvent<GetWeatherByZipCodeCompletedEventArgs>> _weather;
Next, change the GetWeatherSubject function to the following:
private void GetWeatherSubject()
{
if (_weather == null)
{
_weather = Observable.FromEvent<svcWeather.GetWeatherByZipCodeCompletedEventArgs>(weatherClient, "GetWeatherByZipCodeCompleted");
}
}
Finally, change the WireUpWeatherEvents method to look like the following (notice how the timeout value is now set to a more reasonable five seconds as well):
private void WireUpWeatherEvents()
{
GetWeatherSubject();
_weather.ObserveOn(Deployment.Current.Dispatcher)
.Timeout(TimeSpan.FromSeconds(5))
.Subscribe(evt =>
{
if (evt.EventArgs.Result.Details != null)
{
lblWeatherFahrenheit.Text = "Current Weather, Fahrenheit: " + evt.EventArgs.Result.Details[0].MinTemperatureF.ToString() + " - " + evt.EventArgs.Result.Details[0].MaxTemperatureF.ToString();
lblCelsius.Text = "Current Weather, Celsius: " + evt.EventArgs.Result.Details[0].MinTemperatureC.ToString() + " - " + evt.EventArgs.Result.Details[0].MaxTemperatureC.ToString();
imgWeather.Source = new BitmapImage(new Uri(evt.EventArgs.Result.Details[0].WeatherImage, UriKind.Absolute));
}
},
ex =>
{
Deployment.Current.Dispatcher.BeginInvoke(() => lblStatus.Text = ex.Message);
Deployment.Current.Dispatcher.BeginInvoke(() =>
btnQuit.Visibility=System.Windows.Visibility.Visible);
Deployment.Current.Dispatcher.BeginInvoke(() => btnRetry.Visibility =
System.Windows.Visibility.Visible);
}
);
}
This walkthrough
illustrates one approach to handling connection issues on Windows Phone 7
devices: you specify a timeout period, and if you don't get a response
within that period, you prompt the user to retry or to quit.