Windows Phone 8 - The new map services

by CameronM 10. December 2012 17:11

One of the really nice enhancements that have been made to the mapping capabilities in the Windows Phone 8 SDK is the addition of services such as geocoding and reverse geocoding, which are functions that are often required when building map-based solutions.

I wrote a post some time ago showing how you could utilise the Bing Maps API to perform these tasks, but in WP8, they’re built in to the SDK. GeocodeQuery and ReverseGeocodeQuery are two classes in the new Microsoft.Phone.Maps.Services namespace that provide these function. 

GeocodeQuery

Geocoding is the process of retrieving a geographical location (latitude/longitude) when provided a physical address, such as a street and suburb name. You’d use geocoding in your app if you want users to enter an address in a textbox and then see that displayed on a map.

The code to perform a GeocodeQuery couldn't be much easier. Assuming you have a TextBox name SearchTextBox where the user will enter the address to query and a Button that they press, your code to perform the query will look as simple as this.

private void SearchButton_Click(object sender, RoutedEventArgs e)
{
    GeocodeQuery query = new GeocodeQuery();
    query.SearchTerm = SearchTextBox.Text;
    query.GeoCoordinate = new System.Device.Location.GeoCoordinate(-27.5, 153);
    query.QueryCompleted += query_QueryCompleted;
    query.QueryAsync();
}

You will need to decide how to handle the results of the query, which if successful will be a list of MapLocation objects. For this example we'll just display the street address of the first record, but obviously you could display the results in a list and let the user select the relevant record.

void query_QueryCompleted(object sender, QueryCompletedEventArgs<IList<MapLocation>> e)
{
    //check that the query didn't raise an exception
    if(e.Error==null)
    {
        //grab the first location//
        if (e.Result.Count() > 0)
        {
            var location = e.Result.FirstOrDefault();
            MessageBox.Show(location.Information.Address.Street);
        }
    }
}

The MapLocation class contains a number of properties, including GeoCoordinate (latitide/longitude) and Information. The Information property returns a LocationInformation object that can be used to retrieve values such as the Address, Description and Name of the location. Depending on the addres that was entered, not all of these values will be populated. For example, if the user enters a regular suburban address, only the Address property is populated.

ReverseGeocodeQuery

As the name suggests, reverse geocoding is the process of retrieving a physical address (street/suburb) when provided a geographical location (latitude/longitude). You’d use reverse-geocoding in your app if you wanted users to be able to tap a point on a map and see what the address is.

To illustrate the code to perform a ReverseGeocodeQuery, we’ll need a simple UI that allows a user to select a location on a map. You can either add a map via code or in XAML, but we’ll use XAML for this example.

Firstly add the XML namespace to your page declaration. 

xmlns:maps="clr-namespace:Microsoft.Phone.Maps.Controls;assembly=Microsoft.Phone.Maps"

Add a map control and set an appropriate Center and ZoomLevel and add the Tap event handler. 

<maps:Map x:Name="LocationMap" Center="-27.5, 153" ZoomLevel="10" Tap="LocationMap_Tap"  />

Next we’ll need to handle the Tap event, which will be triggered when the user taps the map. 

private void LocationMap_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
    //get the location of the Tap
    GeoCoordinate location = LocationMap.ConvertViewportPointToGeoCoordinate(e.GetPosition(LocationMap));
 
    //reverse geocode the location
    ReverseGeocodeQuery reverse = new ReverseGeocodeQuery();
    reverse.GeoCoordinate = location;
    reverse.QueryCompleted += reverse_QueryCompleted;
    reverse.QueryAsync();
}

Lastly, you'll want to handle the callback from when the query completes. This could be as simple or as complex as you like, but for this example we'll just show the street name of the location.

void reverse_QueryCompleted(object sender, QueryCompletedEventArgs<IList<MapLocation>> e)
{
    // do something with the address
    if(e.Error==null)
    {
        //grab the first location
        if (e.Result.Count() > 0)
        {
            var location = e.Result.FirstOrDefault();
            MessageBox.Show(location.Information.Address.Street);
        }        
    }
}

Tags: , ,

Windows Phone 8 | WP8