How to display route and directions on a map in Windows Phone 8

[ This article is for Windows Phone 8 developers. If you’re developing for Windows 10, see the latest documentation. ]

This topic describes how to display the route and directions from your phone’s current location to a specified location on a map in Windows Phone 8.

Tip

This topic describes how to write code that displays route and directions inside your app. If you simply want to display directions, you can also use the Maps directions task, which launches the built-in Maps app. For more info, see How to use the Maps directions task for Windows Phone 8.

Consider the possibility of adding text-to-speech output. For more info, see Text-to-speech (TTS) for Windows Phone 8.

This topic contains the following sections.

Getting the phone’s current location

To get the phone’s current location

  1. In Visual Studio, create a new Windows Phone 8 project.

  2. Select the ID_CAP_LOCATION and the ID_CAP_MAP capabilities in the app manifest file.

    1. In Solution Explorer, expand the Properties folder in a C# project or the My Project folder in a Visual Basic project. In a Visual Basic project, you may have to click Show all files before you can expand the My Project folder.

    2. In the expanded folder, locate and open the app manifest file, WMAppManifest.xml.

    3. In Manifest Designer, on the Capabilities page, check the ID_CAP_LOCATION and the ID_CAP_MAP capabilities.

    4. Save your changes and close Manifest Designer.

  3. In MainPage.xaml.cs or MainPage.xaml.vb, replace the default code with the following code. This code get the phone’s current location and adds the phone’s current location coordinates to the MyCoordinates collection.

    using System;
    using System.Collections.Generic;
    using System.Windows;
    using Microsoft.Phone.Controls;
    using System.Device.Location;
    using Windows.Devices.Geolocation;
    using Microsoft.Phone.Maps.Services;
    using Microsoft.Phone.Maps.Controls;
    
    namespace RouteDirectionsTopic
    {
        public partial class MainPage : PhoneApplicationPage
        {
            List<GeoCoordinate> MyCoordinates = new List<GeoCoordinate>();
    
            // Constructor
            public MainPage()
            {
                InitializeComponent();
                this.GetCoordinates();
            }
    
            private async void GetCoordinates()
            {
                // Get the phone's current location.
                Geolocator MyGeolocator = new Geolocator();
                MyGeolocator.DesiredAccuracyInMeters = 5;
                Geoposition MyGeoPosition = null;
                try
                {
                    MyGeoPosition = await MyGeolocator.GetGeopositionAsync(TimeSpan.FromMinutes(1), TimeSpan.FromSeconds(10));
                    MyCoordinates.Add(new GeoCoordinate(MyGeoPosition.Coordinate.Latitude, MyGeoPosition.Coordinate.Longitude));
                }
                catch (UnauthorizedAccessException)
                {
                    MessageBox.Show("Location is disabled in phone settings or capabilities are not checked.");
                }
                catch (Exception ex)
                {
                    // Something else happened while acquiring the location.
                    MessageBox.Show(ex.Message);
                }
            }
        }
    }
    
    Imports System
    Imports System.Collections.Generic
    Imports System.Windows
    Imports Microsoft.Phone.Controls
    Imports Location = System.Device.Location
    Imports Geolocation = Windows.Devices.Geolocation
    Imports Microsoft.Phone.Maps.Services
    Imports Microsoft.Phone.Maps.Controls
    
    Partial Public Class MainPage
        Inherits PhoneApplicationPage
    
        Dim MyCoordinates As New List(Of Location.GeoCoordinate)()
    
        ' Constructor
        Public Sub New()
    
            InitializeComponent()
            GetCoordinates()
    
        End Sub
    
        Private Async Sub GetCoordinates()
    
            ' Get the phone's current location.
            Dim MyGeolocator As New Geolocation.Geolocator()
            MyGeolocator.DesiredAccuracyInMeters = 5
            Dim MyGeoPosition As Geolocation.Geoposition = Nothing
            Try
                MyGeoPosition = Await MyGeolocator.GetGeopositionAsync(TimeSpan.FromMinutes(1), TimeSpan.FromSeconds(10))
                MyCoordinates.Add(New Location.GeoCoordinate(MyGeoPosition.Coordinate.Latitude, MyGeoPosition.Coordinate.Longitude))
            Catch uaex As UnauthorizedAccessException
                MessageBox.Show("Location is disabled in phone settings or capabilities are not checked.")
            Catch exc As Exception
                ' Something else happened while acquiring the location.
                MessageBox.Show(exc.Message)
            End Try
        End Sub
    
    End Class
    

Displaying the route from the phone’s current location to a location on a map

This code sample provides the coordinates of the phone’s current location as a search hint to the query that finds the destination. The phone’s current location is assumed to be Redmond, Washington, which is not far from the specified destination (Seattle, Washington).

To display the route from the phone’s current location to a location on a map

  1. In MainPage.xaml, add a Map control inside the grid named ContentPanel as shown in the following code. For more info about adding a Map control, see How to add a Map control to a page in Windows Phone 8.

    <maps:Map x:Name="MyMap" Grid.Row="1" Center="47.6268, -122.2460" ZoomLevel="11"/>
    

    If you add the control by writing XAML, you also have to add the following xmlns declaration to the phone:PhoneApplicationPage element. If you drag and drop the Map control from the Toolbox, this declaration is added automatically.

    xmlns:maps="clr-namespace:Microsoft.Phone.Maps.Controls;assembly=Microsoft.Phone.Maps"
    
  2. In MainPage.xaml.cs or MainPage.xaml.vb, in the MainPage class, create the following class-level variables.

            RouteQuery MyQuery = null;
            GeocodeQuery Mygeocodequery = null;
    
        Dim MyQuery As RouteQuery
        Dim Mygeocodequery As GeocodeQuery
    
  3. In the GetCoordinates() method, after the code in the try block, add the following code. This code sets the destination address entered by the user as the SearchTerm of the GeocodeQuery, and then converts the address to geocoordinates. Then the code sets these geocoordinates as the GeoCoordinate of the GeocodeQuery.

                    Mygeocodequery = new GeocodeQuery();
                    Mygeocodequery.SearchTerm = "Seattle, WA";
                    Mygeocodequery.GeoCoordinate = new GeoCoordinate(MyGeoPosition.Coordinate.Latitude, MyGeoPosition.Coordinate.Longitude);
    
                Mygeocodequery = New GeocodeQuery()
                Mygeocodequery.SearchTerm = "Seattle, WA"
                Mygeocodequery.GeoCoordinate = New Location.GeoCoordinate(MyGeoPosition.Coordinate.Latitude, MyGeoPosition.Coordinate.Longitude)
    
  4. In the GetCoordinates() method, after the code in the try block, add the following code. This code attaches an event handler named Mygeocodequery_QueryCompleted to the QueryCompleted event and calls the QueryAsync method of the GeocodeQuery.

                    Mygeocodequery.QueryCompleted += Mygeocodequery_QueryCompleted;
                    Mygeocodequery.QueryAsync();
    
                AddHandler Mygeocodequery.QueryCompleted, AddressOf Mygeocodequery_QueryCompleted
                Mygeocodequery.QueryAsync()
    
  5. Add the Mygeocodequery_QueryCompleted event handler to the class. This code creates a new RouteQuery object and stores the coordinates of the current location and the specified destination in the Waypoints property of the RouteQuery. It also attaches an event handler named MyQuery_QueryCompleted to the QueryCompleted event of the RouteQuery.

            void Mygeocodequery_QueryCompleted(object sender, QueryCompletedEventArgs<IList<MapLocation>> e)
            {
                if (e.Error == null)
                {
                    MyQuery = new RouteQuery();
                    MyCoordinates.Add(e.Result[0].GeoCoordinate);
                    MyQuery.Waypoints = MyCoordinates;
                    MyQuery.QueryCompleted += MyQuery_QueryCompleted;
                    MyQuery.QueryAsync();
                    Mygeocodequery.Dispose();
                }
            }
    
        Private Sub Mygeocodequery_QueryCompleted(sender As Object, e As QueryCompletedEventArgs(Of IList(Of MapLocation)))
            If e.[Error] Is Nothing Then
                MyQuery = New RouteQuery()
                MyCoordinates.Add(e.Result(0).GeoCoordinate)
                MyQuery.Waypoints = MyCoordinates
                AddHandler MyQuery.QueryCompleted, AddressOf MyQuery_QueryCompleted
                MyQuery.QueryAsync()
                Mygeocodequery.Dispose()
            End If
        End Sub
    
  6. Add the MyQuery_QueryCompleted event handler to the class. This code adds a route on the map between the two geocoordinate objects in MyCoordinates.

            void MyQuery_QueryCompleted(object sender, QueryCompletedEventArgs<Route> e)
            {
                if (e.Error == null)
                {
                    Route MyRoute = e.Result;
                    MapRoute MyMapRoute = new MapRoute(MyRoute);
                    MyMap.AddRoute(MyMapRoute);
                    MyQuery.Dispose();
                }
            }
    
        Private Sub MyQuery_QueryCompleted(sender As Object, e As QueryCompletedEventArgs(Of Route))
            If e.[Error] Is Nothing Then
                Dim MyRoute As Route = e.Result
                Dim MyMapRoute As New MapRoute(MyRoute)
                MyMap.AddRoute(MyMapRoute)
                MyQuery.Dispose()
            End If
        End Sub
    

Displaying directions from the phone’s current location to a location on a map

To display directions from the phone’s current location to a location on a map

  1. In MainPage.xaml, delete the entire Grid named LayoutRoot and replace it with the following code. This code adds a LongListSelector control below the map control to display the directions between the two locations.

    <phone:PhoneApplicationPage.Resources>
       <DataTemplate x:Key="RouteListTemplate">
          <TextBlock Text="{Binding}" FontSize="{StaticResource PhoneFontSizeMedium}" Margin="5,5,0,0"/>
       </DataTemplate>
    </phone:PhoneApplicationPage.Resources>
    
    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid x:Name="LayoutRoot" Background="Transparent">
       <Grid.RowDefinitions>
          <RowDefinition Height="auto"/>
          <RowDefinition Height="*"/>
          <RowDefinition Height="auto"/>
          <RowDefinition Height="*"/>
       </Grid.RowDefinitions>
       <TextBlock Text="Map Route" Grid.Row="0" FontSize="{StaticResource PhoneFontSizeLarge}" Margin="0,0,0,20"/>
       <maps:Map x:Name="MyMap" Grid.Row="1" Center="47.6268, -122.2460" ZoomLevel="11"/>
       <TextBlock Text="Route Directions" Grid.Row="2" FontSize="{StaticResource PhoneFontSizeLarge}" Margin="0,10,0,20"/>
       <phone:LongListSelector x:Name="RouteLLS" Grid.Row="3" Background="Transparent" ItemTemplate="{StaticResource RouteListTemplate}" LayoutMode="List" 
          IsGroupingEnabled="False"/>
    </Grid>
    

    After adding this XAML code, here is what you see in the designer.

  2. In MainPage.cs or MainPage.xaml.vb, add the highlighted code to the MyQuery_QueryCompleted event handler to display the route between the locations.

            void MyQuery_QueryCompleted(object sender, QueryCompletedEventArgs<Route> e)
            {
                if (e.Error == null)
                {
                    Route MyRoute = e.Result;
                    MapRoute MyMapRoute = new MapRoute(MyRoute);
                    MyMap.AddRoute(MyMapRoute);
    
                    List<string> RouteList = new List<string>();
                    foreach (RouteLeg leg in MyRoute.Legs)
                    {
                        foreach (RouteManeuver maneuver in leg.Maneuvers)
                        {
                            RouteList.Add(maneuver.InstructionText);
                        }
                    }
    
                    RouteLLS.ItemsSource = RouteList;
    
                    MyQuery.Dispose();
                }
            }
    
        Private Sub MyQuery_QueryCompleted(sender As Object, e As QueryCompletedEventArgs(Of Route))
            If e.[Error] Is Nothing Then
                Dim MyRoute As Route = e.Result
                Dim MyMapRoute As New MapRoute(MyRoute)
                MyMap.AddRoute(MyMapRoute)
    
                Dim RouteList As New List(Of String)()
                For Each leg As RouteLeg In MyRoute.Legs
                    For Each maneuver As RouteManeuver In leg.Maneuvers
                        RouteList.Add(maneuver.InstructionText)
                    Next
                Next
    
                RouteLLS.ItemsSource = RouteList
    
                MyQuery.Dispose()
            End If
        End Sub
    

Results

The following screenshot displays the result of running the sample that you created in this topic.

Make sure that location is enabled in settings on the device on which you test the app.

See Also

Reference

Map

Other Resources

How to add UIElements to a Map control in Windows Phone 8