WeatherView Sample

This is a walkthrough for creating a universal Windows app written in C#, that runs on both Windows 8.1 and Windows Phone 8.1. You can see the app which the sample creates on the Windows Store and the Windows Phone Store.

App in Windows App store

Windows Store link

Windows Phone store link

 

What the app does

This app uses geolocation and two web services to create a graphical weather app. First, it uses your location to create a query to send to the Weather Underground web service. This service returns a JSON string, which we parse to extract the current weather, and two forecasts.

We then take this weather, and display it but more interestingly, we ask Bing for an image to go with it. For example, if the weather forecast is “raining frogs” we ask Bing for some images related to “raining frogs”, and then display that in the background.

 

What you need to do

As this app uses some webservices, you will need to create accounts with them in order to obtain API keys. Without the keys, the app will not function. The good news is that you can obtain these keys for free, although they may time-out, or only operate for a set number of calls per month. If you are going to write a commercial app, you need to carefully consider the terms, conditions and potential costs of using the web services. For experimenting, the free accounts are more than adequate.

Weather Underground account

Azure / Bing Services account

 

Structure of the app

The app is a universal app, which means it contains both the desktop and the phone projects within the one Visual Studio solution. You can choose which to build by selecting the default start-up project.

Both projects share the same MainPage.xaml and C# code-behind source, and the MainPageViewModel. There are a few cases when some Phone-specific or Desktop-specific is commented out for compile time. For example, the Phone does not need the SettingsFlyout code.

The app is written following the MVVM design model, and so the XAML file references parameters which are defined in the MainPageViewModel.

Program flow

The program launches and immediately tries to obtain the current location in FindUser.

One the location has been obtained, the latitude and longitude are passed into WeatherUnderGroundQuery. This method uses the HttpClient to get the latest weather information:

public async Task WeatherUndergroundQuery(double latitude, double longitude)
       {
           using (var client = new HttpClient(new HttpClientHandler(), true))
           {
               string q = string.Format("http://api.wunderground.com/api/<your WU key here>/conditions/forecast/geolookup/q/{0},{1}.json", latitude, longitude);
               var data = await client.GetStringAsync(q);
 
               // The weather data was obtained. Process the JSON string it returned.
               ProcessWeatherData(data.ToString());
           }
       }
 

The method ProcessWeatherData takes the result, and using JsonObject.Parse, breaks it down to extract the forecast data. This data is displayed, but also takes a descriptive string returned by WeatherUnderground, and passes it to the BingQuery method.

public async Task BingQuery(string query)
       {
           // Query the Bing search engine to return an image related to the input string
           using (var client = new HttpClient(new HttpClientHandler(), true))
           {
               var bingKey = "<your Bing key here>";
               var authentication = string.Format("{0}:{1}", string.Empty, bingKey);
               var encodedKey = Convert.ToBase64String(Encoding.UTF8.GetBytes(authentication));
                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", encodedKey);
               string q = string.Format("https://api.datamarket.azure.com/Data.ashx/Bing/Search/v1/Image?Query=%27{0}%27&Adult=%27strict%27&$top=3&$format=JSON", query);
               var data = await client.GetStringAsync(q);
 
               // Bing query returned results, which now need processed
               ProcessSearch(data);
           }
       }
 

BingQuery constructs a query, again using HttpClient, and when it returns, passes the result to ProcessSearch.

private void ProcessSearch(string jsondata)
       {
           // Process the Bing return string and display the resulting image
           JsonObject jsonObject = JsonObject.Parse(jsondata);
           JsonArray jsonResults = jsonObject["d"].GetObject()["results"].GetArray();
           string weather_image = jsonResults[0].GetObject()["MediaUrl"].GetString(); 
           CurrentConditionsImage= BitmapFromString(weather_image);
           ProgressVisible = false;
       }

The path to the image returned by the query is converted to a bitmap, and when displayed in the XAML image control.

 

private BitmapImage BitmapFromString(string weather_image)

     {

           // Helper function to create a bitmap from a string containing a URI

           if (weather_image == null) return null;

           BitmapImage bitmapImage = new BitmapImage();

           bitmapImage.UriSource = new Uri(weather_image);

           return bitmapImage;

       }

 

The entire process takes only a few seconds. If the calls time-out, an exception is caught and some apologetic information and default images are displayed.

Last edited May 27, 2014 at 11:12 PM by CraicDesign, version 1