Getting started with Bing Maps SDK for Windows Store apps

Bing Maps SDK for Windows Store enables Windows 8 developers to include a rich mapping experience in C#, C++, VB.NET and JavaScript applications. After a couple of beta releases, the SDK finally reached RTM status that allows for Windows Store submissions. This is an introductory post that is meant to investigate basic functionality provided in Bing Maps components for C#/XAML Windows Store apps.

In particular I will look into following topics:

  • using  Bing Maps SDK for Windows Store apps in Visual Studio 2012 projects,
  • zooming and centering map on user's current location using geolocation service,
  • adding pushpins,
  • drawing polygons,
  • adding other UIElements to the map.

Prerequisites

First of all we will need to get Bing Maps SDK for Windows Store apps which is located here. After installing the extension Bing Maps SDK will be available in Windows Store apps in Reference Manager.

Make sure to select Microsoft Visual C++ Runtime Package as it required by maps components. Because Bing Maps native implementation, we need to change Active solution configuration to either ARM, x86 or x64. Otherwise the project will not compile.

There is one last step required to start using the components - you will need a Bing Maps Key for Windows Store appsThere are three types of keys available - Trial, Basic and Enterprise, you can learn about differences between them here. I am using a Trial key, but when writing real world Windows 8 apps you are most likely to use Basic.

In order to generate the key go to https://www.bingmapsportal.com/, login with your Live ID (if you dont have it you will need to create one) and click on Create or view keys under My Account section.

Now we are good to go - let's create a new Windows Store app (I am using Blank App template).

<Page  
    (...)
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:Maps="using:Bing.Maps"
    mc:Ignorable="d">
    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <Maps:Map Credentials="INSERT_YOUR_KEY" x:Name="BingMap">
        </Maps:Map>
    </Grid>
</Page>

Instead of hardcoding the key in pages, it is usually better to have it defined in a resource dictionary (eg. in App.xaml).

Centering and zooming in on current location

Let's start with the basics and show how to center and zoom the map based on current location. Before running this example make sure that Location capability is enabled in Package.appxmanifest.

protected async override void OnNavigatedTo(NavigationEventArgs e)  
{
    Location location = await GetCurrentLocationAsync();
    CenterOnLocation(location);
}

private async Task<Location> GetCurrentLocationAsync()  
{
    var geolocator = new Geolocator();
    Geoposition currentGeoposition = await geolocator.GetGeopositionAsync();
    var location = new Location()
    {
        Latitude = currentGeoposition.Coordinate.Latitude,
        Longitude = currentGeoposition.Coordinate.Longitude,
    };
    return location;
}

private void CenterOnLocation(Location location)  
{
    BingMap.Center = location;
    BingMap.ZoomLevel = ZoomLevel;
}

Using geolocation features of Windows 8 is really straightforward and is further simplified by async/await pattern. After the page gets navigated to, map control should be automatically centered on current location.

Adding pushpins

Pushpins can be added to the map either in XAML or imperatively in code-behind.

<Maps:Map Credentials="YOUR_KEY_HERE"  
          x:Name="BingMap">
    <Maps:Map.Children>
        <Maps:Pushpin Text="1">
            <Maps:MapLayer.Position>
                <Maps:Location Latitude="50.0104955"
                                          Longitude="21.9888709"/>
            </Maps:MapLayer.Position>
        </Maps:Pushpin>
    </Maps:Map.Children>            
</Maps:Map>

Please note that in order to define pushpin position on the map we are setting MapLayer.Position attached property.

private void AddPushpin(Location location, string text)  
{
    var pushpin = new Pushpin()
                          {
                              Text = text,
                          };
    MapLayer.SetPosition(pushpin, location);
    BingMap.Children.Add(pushpin);
}

Default pushpin template should look like this:

In order to add some interactivity to the pushpin, we can handle Tapped event like this:

<Maps:Pushpin Text="1" Tapped="PushpinTapped">  
    <Maps:MapLayer.Position>
        <Maps:Location Latitude="50.0104955" 
                       Longitude="21.9888709"/>
    </Maps:MapLayer.Position>
</Maps:Pushpin>
private async void PushpinTapped(object sender, TappedRoutedEventArgs e)  
{            
    var dialog 
        = new MessageDialog("Congratulations. You tapped a pushpin.");
    await dialog.ShowAsync();
}

Drawing polygons

Bing Maps groups shapes (such as polygons and polylines) into layers represented by MapShapeLayer objects. Polygons are drawn using MapPolygon objects with vertices specified in Locations property. Following example creates a semi-transparent overlay for New Mexico state.

<Maps:Map Credentials="YOUR_KEY_HERE"  
          x:Name="BingMap">    
    <Maps:Map.ShapeLayers>
        <Maps:MapShapeLayer>
            <Maps:MapShapeLayer.Shapes>
                <Maps:MapPolygon FillColor="#5000ff00">
                    <Maps:MapPolygon.Locations>
                        <Maps:Location Latitude="36.9971" Longitude="-109.0448"/>
                        <Maps:Location Latitude="31.3337" Longitude="-109.0489"/>
                        <Maps:Location Latitude="31.3349" Longitude="-108.2140"/>
                        <Maps:Location Latitude="31.7795" Longitude="-108.2071"/>
                        <Maps:Location Latitude="31.7830" Longitude="-106.5317"/>
                        <Maps:Location Latitude="32.0034" Longitude="-106.6223"/>
                        <Maps:Location Latitude="31.9999" Longitude="-103.0696"/>
                        <Maps:Location Latitude="36.9982" Longitude="-103.0023"/>
                        <Maps:Location Latitude="36.9982" Longitude="-109.0475"/>
                    </Maps:MapPolygon.Locations>
                </Maps:MapPolygon>
            </Maps:MapShapeLayer.Shapes>
        </Maps:MapShapeLayer>
    </Maps:Map.ShapeLayers>
</Maps:Map>

And here is the result:

Adding other UIElements to the map

Map.Children property is actually a MapUIElementCollection object, which means we can add any UIElement to it. This opens a whole new set of possibilities, especially if you think of all the neat features XAML has to offer. To position elements we need to set MapLayer.Position attached property, just like in pushpin example (Pushpin is a UIElement as well). Here is an example that uses Image control.

<Maps:Map.Children>  
    <Maps:Pushpin Text="1" Tapped="PushpinTapped">
        <Maps:MapLayer.Position>
            <Maps:Location Latitude="50.0104955" 
                           Longitude="21.9888709"/>
        </Maps:MapLayer.Position>
    </Maps:Pushpin>
    <Image Source="Assets/Rain.png" Stretch="None">
        <Maps:MapLayer.Position>
            <Maps:Location Latitude="47.9097" 
                           Longitude="-122.6331"/>
        </Maps:MapLayer.Position>
    </Image>
</Maps:Map.Children>

This will add a rain icon over Seattle. No pun intended.

Hope you will find this post helpful!

comments powered by Disqus