Building an Airport Status Mashup with Silverlight and Bing Maps

Djonatas Tenfen demonstrates in fine detail how to quickly and easily build a mashup Silverlight application to consume and manipulate multiple data sources, and plot airports' realtime status onto a map.

In this article, I’ll show you how to use some of the features of Bing maps, and how to use the data Bing provides to build a Silverlight application to show the status of U.S. airports. I’ll break this project down into fine-grained steps so that you can see each aspect of it, and we’ll walk through the creation of the application from start to finish to get a thorough understanding of how this kind of application is put together. So, let’s get started!


Before we can actually start building the Silverlight application and doing cunning things with data, we need to set ourselves up to be able to use Bing’s services.


First of all, you need to register on the Bing developer site. Click on Create an AppID (in the top right-hand corner), and you’ll need to enter your LiveID (or create one if you don’t have one already), and then submit some basic information such as Application Name, Description, Company Name and email address. It’s worth remembering that despite the registration for the service, Bing is currently free.

Download the SDK

After completing registration, head back to the Bing developer site, log in, and click on Download the SDK. You’ll be directed to the Microsoft Download Center to get a copy of the SDK, which is currently on version 2.0. Simply download the kit and perform the installation as you would for any other SDK.

Creating the Application

After you’ve registered and downloaded the SDK, open Visual Studio 2010 and create a “Silverlight Application” project; in my example, I will name the application AirportStatus_BingMaps (as you can see in figure 1), and to facilitate the publication of the application I’ll create a Web Site from the “Silverlight Application” template, as recommended.


Figure 1. Creating the Silverlight Application project (click on the image for an enlarged view).

Referencing the Assemblies

Now that we have created the application, we’ll reference the Assemblies necessary to present the maps in the application.

To select the Assemblies, right-click on the AirportStatus_BingMaps Silverlight project, select “Add Concerning …“, select the Browse tab, and navigate to the C:\Program Files\Bing Maps Silverlight Control\V1\Libraries directory. Select the files Microsoft.Maps.MapControl.Common.dll and Microsoft.Maps.MapControl.dll, and don’t forget to confirm that the references have been added to your project correctly.

Creating the Map

Now that we’ve created the application and referenced the assemblies, we can create a map within the project. Inside the MainPage.xaml file, within the LayoutRoot grid and just below the line:

Now that we’ve added the columns (which will, in turn, determine the layout of our application) we’ll add the namespace that will reference Bing maps. Just above the same line in MainPage.xaml as before, reference the namespace using the syntax:

In the area reserved for the declaration of the XAML namespace, you should see the complete list of references:

Now that the assembly is referenced within our XAML, and basic layout of the application has been created, we can finally create the map. Just below the layout definition on the </ Grid.ColumnDefinitions> line, add the control (obviously, substituting “Your Bing Maps Key” as appropriate):

This control has some properties which I’ll explain: First, it calls Bing the alias for the namespace, and uses this alias to call the controls contained within this namespace, followed by the alias name (myMAP). The control that we are calling in the current situation is the Map, which is followed by the CredentialsProvider property, where you need to input the registry key that your were emailed when registering with the Bing Developer Center. The second property, Mode, indicates what type of map is loaded (Road or Aerial view), and finally we have the property that indicates the name of control, as mentioned a moment ago. To verify your coding, run the application, and the result should look like Figure 2.


Figure 2. The basic Silverlight application, calling a map from Bing (click on the image for an enlarged view).

Building the Airport Class

To improve the function of our currently basic application, let’s create a class that will contain all (or almost all) U.S. airports with their current status. To create the class, just hit Shift + Alt + C, select Class from the Add New Item window, and change the class name to “Airport” and the file name to Airport.cs. Now that the class is created, add the class properties as listed below:

Note that the Location property does not have a primitive type, so the type is resolved using the Microsoft.Maps.MapControl which we added in the header file.

Loading the XML file

Luckily for you, the details of the names and airport codes of the U.S. airports are contained in an XML file which I’ve already created, which can be downloaded from here. This file contains almost all U.S. airports, although you should note that it only contains their airport codes and names; the exact location of the airports identified will be found using a WCF service from Bing. To add the file to the project, you can simply download it and save it directly into the project.

Bing’s WCF Reference Service

To consume the services of Bing maps, right-click on the AirportStatus_BingMaps project and click on Add Service and, in the Address property, enter: (editor’s note: this has been retired in the current version of Bing Maps)

This service is responsible for conducting searches of locations and drawing routes, among other things. More details of the service and the Bing SDK can be found on Microsoft’s interactive Maps Control SDK demonstration site. After entering the address into the application, click on GO, wait while the service is loaded, and you should eventually see something like figure 3, with the service referenced and loaded. For the rest of the article, I’ll simply refer to the service as “Geoservices”.


Figure 3. Bing’s WCF Geoservices, references and loaded.

Reading Airports.XML and Consuming the WCF Service

Now that we have the service configured and the list of airports, we need to use the data we have to find the position of each airport. So, go back to the MainPage.xaml file and, just below the <Bing: Map CredentialsProv … >line, add the following code:

In this code I am simply creating a container called StackPanel and putting some controls around it; namely a Button and a ListBox. Note that we’ve changed the DataTemplate of the Listbox so that the information is consistently being displayed as “ID – Name”, and note also that the XAML coding part of this project is finished!
Next, we’ll open MainPage.xaml.cs and create a method that will read the Airports.xml file and then search for each airports’ location through the Bing Geoservices. First add the references for the Microsoft.Maps.MapControl and System.Xml.Linq namespaces, and then create the following two private properties in MainPage.xaml.cs (I will not use the MVVM pattern in this article):

These properties will help us to consume the Bing services; the _geoservice is just a reference to the Bing service, and _geocodeRequest is where we will create the credentials that will be sent with the request that we’ll generate in just a moment. The third property is a generic list of type Airport, which will contain the list of airports for as long as the application is live.

Now that the ancillary properties have been generated, we can create a GetAirports method to read the Airport.xml file and transform each entry into an Airport object to be added to the Airports list. To add the necessary System.Xml.Linq assembly to AirportStatus_BingMaps, you follow the same process as when we added the assemblies at the start of the article, although this time you’ll need to navigate to the C:\Program Files\Microsoft SDKs\Silverlight\v4.0\Libraries Client\ directory and select the System.Xml.Linq.dll file (don’t forget to confirm that the reference is added correctly). Now we can add the following code to the MainPage.xaml.cs file:

Don’t forget to add the Microsoft.Maps.MapControl and System.Xml.Linq namespaces, or obviously none of this will work.

Here’s what’s happening in this method:

  • It first creates a local variable of type XDocument that will read the XML file through LinqToXML,
  • A private property receives an instance of the previously-created GeocodeRequest class,
  • An instance of the Credentials class is created, which will load the credentials that we mentioned at the start of the article,
  • The _geocodeRequest.Credentials.ApplicationId property is altered, receiving the ApplicationId  in the myMAP control via XAML,
  • A command-type foreach loop is created, which will traverse the entire airports.xml file and, for each Airport Node, create an instance of Airports and add it to the private property of type list<Airport> “Airports”.

Finally, note that the last foreach line is calling another method, which is responsible for making the location search work; this Search method is described below:

The method first confirms that the Geoservice has no other instances running, so as to avoid unnecessary code and unnecessary memory consumption. If the result of this check is null, then the method creates a new instance of the service through the configuration interface of the endpoint, and then adds an EventHandler to the GeocodeCompleted event, which runs at the end of the WebService search, which is an asynchronous WCF service call from the Silverlight application.

Remember, in Silverlight you can only make calls to asynchronous services.

Upon validation and instantiation of the service, we indicate the search query which, in our example, will be the ID of the airport, and then we have an asynchronous call to the method of the newly-created and referenced GeocodeAsync service. Now, we are running the service asynchronously, but we know that the returning results will have to eventually be addressed in order to implement the GeocodeCompleted event, as the code below illustrates:

As you can see, this method is handling the return from the GeocodeCompleted service. Note that validation is performed first , confirming that the service returned successfully, and then we identify if the result is of the “Airport” type. Having performed these validations, we search through our pre-prepared list of airports to find an airport with the same name as the WebService returned (performed by the lambda expression created in the method). After finding the airport in the list, the Location property is just updated to the location obtained from the service. To test the application now, go to the MainPage class constructor and update the following code snippet:

Now run the application and check that the result looks similar to Figure 4:


Figure 4. Running the application with Bing’s WCF Geoservice (click on the image for an enlarged view).

Locating and Marking Airports on the Map

Now that the Geoservice is up and running, and the map is being displayed, we can mark the location of airports on the map. First we’ll create a private property named imageLayer with type MapLayer (private MapLayer imageLayer;), and then locate the GetAirports () method and added the following code to the beginning of the method, before we create a variable of type XDocument doc:

Perhaps you’re wondering what this is? The first is a property receiving an instance of class type MapLayer, which is a kind of layer that can be created on the map and customized with some information, and we add this layer to the map through the Children property of myMAP. Next, we need to find the Search (string id) method and, just below the line:

… we need to add an EventHandler for the GeocodeCompleted event, encoded in a similar way to _geoservce.GeocodeCompleted += new :

Tip:You can use the snippet functionality of Visual Studio in this instance; code to the equality operator and press tab twice, and Visual Studio will handle the creation the method and make the reference to the event.

The code that will be implemented in the _geoservice_GeocodeCompleted method, referenced by the GeocodeCompleted event, is as follows:


Before we continue, you need to add an image to the AirportStatus_BingMaps project through the “Add Existing Item” menu, and change the URI to the name of the image which you’ve added (in my case it was Flag2_Green.png), and ensure that this is reflected in  your method.

First we’re verifying the status of the returned results. If successful (i.e. the result is of type “Airport”) and if the conditions are met, then the method creates an object of type Image, changes some of that object’s properties (such as the image source and size), and then adds the image to the customizable layer that was added to the map earlier. The second parameter of the method, AddChild, indicates the location on the map where the image should be positioned, which in our case is the position returned by the Geoservice airport search.

Next, the method finds the given airport using the description from my imported XML list, and then swaps the Location property in the file with the results from the service, so that we now know the correct position of each airport on the list.

Now that we’ve marked the map with the location of airports, we’ll arrange it so that selecting an airport in the list on the right-hand side of the application will focus on that airport in the map. So, we return to the MainPage.xaml file and locate the lstbAirports ListBox control, and delegate an event for this control by modifying the code to get an XAML statement like this:

Tip: use the NewEventHandler snippet of Visual Studio to create the method in MainPage.xaml.cs automatically.

Next, change the lstbAirports_SelectionChanged method to:

What we did in this method is just to change the SetView property of the map to the location of the airport selected in the list, and the second property is simple the level of zoom.

Now let’s create a new property called uiElements that will be of type Dictionary<Airport, UIElement>; this will map an image to the airport to facilitate the next  step, where we’ll return the service status of the airport. After declaring the Dictionary variable, go to the constructor and instantiate the property immediately after the InitializeComponent () method:

Go to the _geoservice_GeocodeCompleted method and immediately after the line:

… Include this code snippet:

In this snippet we discover whether the airport is on the list of UI elements and, if it’s not, we add the image and airport to the new dictionary, as this will be used in the status mapping later on. Let’s see what the application looks like at this point:


Figure 5. The entire list of airports with their locations displayed on the map (click on the image for an enlarged view).


Figure 6. Selecting Las Vegas airport and automatically having the map focus on it (click on the image for an enlarged view).

Out Of Browser

Now that the application nearly 100% complete, we’ll enable it to exist Out Of Browser. if you look at the layout of the application, you’ll see the Install button in the top right-hand corner. That button is going to install the application on the local machine, so that we can consume an RSS feed without going through security policies and get the desired result: the current status of the airports.

To do this, open the project properties of AirportStatus_BingMaps, navigate to the Silverlight tab and check “Enable application running out of the browser“. Next , click the Out-Of-Browser Settings button, check the “Require elevated trust When running outside the browser ” option, and click OK.


Figure 7. Configuring the Silverlight application to run Out of Browser(click on the image for an enlarged view).

Now that the application is configured to run outside the browser, we close the project properties, go back to MainPage.xaml, and delegate the Install button’s click event:

Now go to MainPage.xaml.cs and locate the btnInstall_Click method created by Visual Studio, and change the code to:

First a validation is performed by checking whether the application is installed or not and, if not, then the method performs the installation. When we start the application in the browser and click on “Install” we’ll see the following dialog:


Figure 8. Installing the application on your local machine.

If we click on Install, the application will then run on our machine as if it were a local executable.

Reading information about the status of airport RSS

Now that the application is running out of browser, it can access the RSS feed from [link deprecated] and use it to find the current status of the US airports. First let’s give MainPage.xaml.cs a way of cleaning the HTML that comes through the RSS feed:

Now we’ll add another method that will request the appropriate RSS feeds:

… and immediately below that, we’ll write a method for handling the return from the RSS feeds and adding the results to our map:

The GetDescription method opens the root URL of the RSS feeds, and searches the titles for the code of the airport it’s currently updating (e.g. LAX), navigating through the possible feeds using the information from our list of airports. The client_DownloadStringCompleted method then takes this information, locates the given airport in the XML list and updates its property value with the current status of the airport, and finds the airport’s corresponding image on the map and sets its property value to match. To call the service that is now contained in the GetDescription (string search) method, find the _geoservice_GeocodeCompleted method, and after the line:

…call the GetDescription method, passing the ID property of the airport variable as a parameter:

The end result should look like this:


Figure 9. The finished application, locating U.S airports and reporting on their current status (click on the image for an enlarged view).


You can download the complete project from the top of this article to see the finished result. This little application only scratches the surface of Bing maps and the services it provides, and is similarly a very basic demonstration of Silverlight’s abilities. Nevertheless, you’ll hopefully agree that this was a very simple application to write, and that it was relatively easy to manipulate multiple data sources to get the desired results.