Maps in Windows Phone 8 and Phone toolkit: a winning team – Part 1

Maps in Windows Phone 8 is probably the biggest evidence of the great partnership between Nokia and Microsoft: in Windows Phone 8 the maps application installed on every device, even the ones made by other manufacturers, is powered by Nokia technologies.

The most interesting news for developers is that also the Maps control has been updated and it introduced many improvements: first of all, performance improvements. Bing Maps control wasn’t good in this and, especially if you tried to add layers or pushpin, you could have experienced really poor performances.

Second, the new control now offers lot of new options: you can enable 3D landmarks, you can switch between day and night colors, you can change the heading and the pitch, you can easily calculate routes and so on.

Adding the map control is very easy: in the XAML you need to add a reference to the Microsoft.Phone.Maps namespace:

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

After that you can insert the Map control simply by declaring it in the XAML:

<maps:Map
    x:Name="myMap"
    Center="30.712474,-132.32691"
    ZoomLevel="17"
    Heading="45"
    Pitch="25"
    CartographicMode="Road"
    ColorMode="Dark"
    PedestrianFeaturesEnabled="True"
    LandmarksEnabled="True"
    />

In this sample you can see an example of many of the properties that are available in the control:

  • Center is the location where the map is centered. It accepts a GeoCoordinate object, which is a complex object that store many geo location properties, like latitude, longitude, altitude and so on.
  • ZoomLevel is the zoom level of the map, from 1 (very far) to 20 (very near).
  • Heading is the rotation of the map.
  • Pitch is the elevation of the map compared to the horizon.
  • CartographicMode is the type of map that is displayed, you can choose between Aerial, Road, Terrain or Hybrid.
  • ColoreMode can be used to improve the readability of the map during night (Dark) and day (Light).
  • LandmarksEnabled can be used to turn on the 3D representation of some important builidings in the map (like monuments, churches and so on).
  • PedestrianFeaturesEnabled can be used to turn elements that are useful for people that is using the map during a walking (like stairs).

One of the coolest feature is that, with the new map control, is really easy to add a layer, that is a collection of elements that are displayed over the map, as you can see in this sample:

private void OnAddShapeClicked(object sender, RoutedEventArgs e)
{
    MapOverlay overlay = new MapOverlay
                             {
                                 GeoCoordinate = myMap.Center,
                                 Content = new Ellipse
                                               {
                                                   Fill = new SolidColorBrush(Colors.Red),
                                                   Width = 40,
                                                   Height = 40
                                               }
                             };
    MapLayer layer = new MapLayer();
    layer.Add(overlay);

    myMap.Layers.Add(layer);
}

 

For every element I want to display on the map I create a MapOverlay object, that has two main properties: GeoCoordinate, with the coordinates where the element should be placed, and Content, which is a generic object property so it accepts any XAML control. In this example, I’m creating a blue circle, using the Ellipse control, that will be placed in the same position where the map is centered.

In the end I simply create a MapLayer and I add to it the MapOverlay object I’ve just created: I could have created many more MapOverlay object and added them to the same MapLayer (or also to a new one). The last step is to add the layer to the map, by simply adding it to the Layers collection, which is a property of the Map control.

Here is the final result:

shape

This feature is very powerful: since the MapOverlay object has a generic Content property, you can customize the overlay elements any way you want. But there’s a downside: there’s nothing ready to be used in the SDK for common scenarios like displaying a pushpin or the user’s location.

So please say hello to the Phone Toolkit, that probably you already know since it’s one of the essentials toolkits for every Windows Phone developers, since it contains many useful controls, helpers and converters that are not available in the SDK, even some of the standard ones that are used in the native application. The Phone Toolkit is available on Codeplex, but the easiest way to add it to your project is using NuGet. In the latest release Microsoft has added, other than some new cool controls and transitions effects, some map utilities. In our scenario we can make use of two nice controls: UserLocationMarker and Pushpin. They both work in the same way: they are overlay elements that are placed on the map over a specific position and they offer a way to interact with them (so that, for example, the user can tap on a pushpin and do something). They only look different: the Pushpin (in the left image) has the same look & feel of the ones that were available in the old Bing Maps and can be used to highlights point of interests in the map; UserLocationMarker (in the right image) is used to identify the position of the user and it has the same look & feel of the one used in the native app.

pushpinuser

How to use pushpins

First let’s see the simplest way to add a single Pushpin or a UserLocationMarker to the map. First you have to declare in the XAML the following namespace:

xmlns:toolkit=”clr-namespace:Microsoft.Phone.Maps.Toolkit;assembly=Microsoft.Phone.Controls.Toolkit”

Then here is a sample XAML:

<maps:Map x:Name="myMap">
    <toolkit:MapExtensions.Children>
        <toolkit:UserLocationMarker x:Name="UserLocationMarker" />
        <toolkit:Pushpin x:Name="MyPushpin" Content="My Position"></toolkit:Pushpin>
    </toolkit:MapExtensions.Children>
</maps:Map>

The first thing is to use the MapExtensions, one of the extensions available in the toolkit. This extension has a Children property, that is the collection of the elements that are displayed over the map. In this code you can see an example of both controls: UserLocationMarker and Pushpin. The only difference is that, for the pushpin, I’ve set the Content property, which is the label displayed on the mark.

If we want to manage them in the code, in order to set the position in the map, we can use the following code:

UserLocationMarker marker = (UserLocationMarker)this.FindName("UserLocationMarker");
marker.GeoCoordinate = myMap.Center;

Pushpin pushpin = (Pushpin)this.FindName("MyPushpin");
pushpin.GeoCoordinate = new GeoCoordinate(30.712474, -132.32691);

First we retrieve the control by using the FindName method and passing as parameter the value of the x:Name property of the control. Then, once we have a reference, we change the value of the GeoCoordinate property. Both controls also have a Tap event, that is triggered when user taps on the pushpin. We can use it to interact with the user, like in the following example:

<maps:Map x:Name="myMap" Height="400">
    <toolkit:MapExtensions.Children>
        <toolkit:Pushpin x:Name="MyPushpin" Content="My Position" Tap="MyPushpin_OnTap" />
    </toolkit:MapExtensions.Children>
</maps:Map>
private void MyPushpin_OnTap(object sender, GestureEventArgs e)
{
    Pushpin pushpin = sender as Pushpin;
    MessageBox.Show(pushpin.Content.ToString());
}

In the XAML we have declared an event handler to manage the Tap event; in the code we get the pushpin that has been tapped (using the sender object that is passed as parameter) and we show the label on the screen using a MessageBox.

A useful converter

If you’ve already played with the geo localization services available in the new Windows Runtime APIs (the same that are available in Windows 8), you should have noticed a weird thing: the class used by the geo localization APIs to store location information is called Geolocalization, while the one used by the map is called GeoLocalization. Unlucky, it’s not a typo, they are two different classes: the result is that you can’t take the information returned by the geo localization APIs and assign it to the map, but you need a conversion. Luckily, the Phone Toolkit contains an extension method to do that, you simply have to add the Microsoft.Phone.Maps.Toolkit to the code and than you can do something like this:

Geolocator geolocator = new Geolocator();
Geoposition geoposition = await geolocator.GetGeopositionAsync();
myMap.Center = geoposition.Coordinate.ToGeoCoordinate();

The ToGeoCoordinate() extension method takes care of converting the Coordinate object returned by the Geolocator class (which type is Geocoordinate) in the correct one required by the map control.

In the next post

In this post we’ve covered some basic scenarios: they are useful to understand how the phone toolkit can be helpful in developing an application that uses maps, but they are not so useful in a real scenario. For example, a real application would have displayed more than one pushpin in the map, in order to display, for example, some point of interests around the user, like restaurants or pubs. In the next post we’ll see how to do that using some concepts every Windows Phone developer should be familiar with: templates and binding.

This entry was posted in Windows Phone and tagged , , . Bookmark the permalink.

18 Responses to Maps in Windows Phone 8 and Phone toolkit: a winning team – Part 1

  1. Pablo says:

    Do you know if it is possible to use your own images from isostorage within Windows 8 map control TileSource? It was not possible on WP7.
    The idea is to provide offline functionalities. Who knows… maybe in-app map purchasing 😉

  2. Ricardo says:

    Well explained, waiting for part2…

  3. Ignacio says:

    UserLocationMarker is always null when I’m trying to set the GeoCoordinate property in CS code. Why?

    • Ignacio says:

      Sloved, I’ve looked at the simple code from NuGet extensión, and found that MapExtensionsSetup method declared on MapsSample.xaml.cs was called in ctor. I did the same on mi maps page code.

      • qmatteoq says:

        Good to know, thanks for sharing!

      • Antownee says:

        Excuse me, but could you kindly clarify how you solved the null reference exception because I’m going through the same issue.

        • qmatteoq says:

          Hi, if you’re talking about the null reference that can occur when you deal with the pushpins, as explained in the post it can happen if the page is not fully initialized. I’ve fixed it by interacting with them in the Loaded event of the page.

  4. Enzo Contini says:

    Nice article!
    I wonder if there is an easy way to get, from a Tap event, a reference to the Item of the pushpin: unfortunatly, it seems to me that only the pushpin displayed content is available from the sender!

  5. peke-tsu says:

    This example just does not work. I made it as simple as possible:

    InitializeComponent();
    UserLocationMarker marker = (UserLocationMarker)this.FindName(“UserLocationMarker”);
    marker.GeoCoordinate = myMap.Center;
    result is:

    $exception {System.NullReferenceException: Object reference not set to an instance of an object. at PhoneApp11.MainPage..ctor()}System.Exception {System.NullReferenceException}

    • qmatteoq says:

      Don’t do it in the page constructor, but in the Loaded event of the page. I suppose that, at that time, the visual controls are not fully initialized yet.

  6. jvinhit says:

    Hey u , i can edit style pushpin toolkit ? Or Image in pushpin.
    and Edit Style Marker ? tks u

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.