Hi guys, in the
last article you learned how to locate a point in the
Bing Map and then add a customized pushpin to this location. Taking a leap further here in this article you'll know how to plot two points on
the map and calculate the route between them. This article would clear all the
queries regarding Bing Map's route problems. Though it may seem too messy with
code but going through each line clearly illustrates the core concepts used and
why and how to be used while working with Windows Phone 7 using Bing Maps.
Follow the steps below.
Step 1 : First of all you need to know all the basic requirements for running a Windows Phone 7 application in your machine and for this refer to the previous articles. Also you must know that this project is made in Windows Phone 7.1 version so mind any discrepancies arising due to version mismatch.
Step 2 : Then open Visual Studio
- Select new project
- Select your preferred language
- Select the Silverlight for Windows Phone application on the left pane and Windows Phone application in right pane.
- Name the project

Step 3 : Now you land up in a screen showing the Windows Phone application and XAML coding into different partition. Now you may change the look of your application as you wish.

Step 4 : Now drag and drop the map control from the toolbox into the phone application.
- Add a textbox and in the properties change the name of this textbox as "fromtxtbx". This text box holds the value of the starting location.
- Add another textbox and in the properties change the name of this textbox as "totxtbx". This text box holds the value of the final destination location.
- Add a button, name it "Change view". This is to change the mode of view of the map.
- Add another button and name it "Route" to find the address on the Bing Map.
Step 5 : Now before we start the coding ahead you need to get the credentials for using the Bing map in Windows Phone application. To know how to get the credentials see this article . If you don't get the credentials then an irritating white strip keeps appearing over the map urging you to get the credentials for using the map control.
Step 6 : When you have the Bing map key, get the credential key and put it here in the XAML part and find the following:
<my:Map
Height="482"
HorizontalAlignment="Left"
Margin="6,6,0,0"
Name="map1"
VerticalAlignment="Top"
Width="444"
CredentialsProvider=
"type the bing map key you got here"/>
Step 7 : Now
add the following references:
-
Go to Solution Explorer
-
Also add a service reference--> Right click on reference
-
Add service reference
-
In the address bar type- http://dev.virtualearth.net/webservices/v1/routeservice/routeservice.svc/mex. This is to use the Route related classes in the application. Name this service reference as routeservice.
-
Add another service reference http://dev.virtualearth.net/webservices/v1/geocodeservice/geocodeservice.svc/mex. This is to use the Geocode related classes in the application. Name this service reference as geocodeservice.
Step 8 : Add the following namespaces to the project:
-
using System;
-
using System.Windows;
-
using System.Windows.Media;
-
using Microsoft.Phone.Controls;
-
using Microsoft.Phone.Controls.Maps;
-
using Microsoft.Phone.Controls.Maps.Platform;
-
using System.Device.Location;
-
using System.Windows.Shapes;
-
using findroute.geocodeservice;
-
using System.Windows.Media.Imaging;
Step 9 : Now here we start first of all globally declare a Location class object so that it can be used throughout the code.
Location location = new Location(); // Global declaration
// Constructor
public MainPage()
{
InitializeComponent();
map1.LogoVisibility = Visibility.Collapsed;
map1.CopyrightVisibility = Visibility.Collapsed;
map1.Mode = new AerialMode();
}
Step 10 : Now define a void type method named "Geocode". This method accepts a geocode query string as well as a "waypoint index", which will be used to track each asynchronous geocode request.
private void Geocode(string strAddress, int waypointIndex)
{
// Here we create the service variable and set the callback method using the GeocodeCompleted property.
findroute.geocodeservice.GeocodeServiceClient geocodeService = new findroute.geocodeservice.GeocodeServiceClient("BasicHttpBinding_IGeocodeService");
geocodeService.GeocodeCompleted += new EventHandler<findroute.geocodeservice.GeocodeCompletedEventArgs>(geocodeService_GeocodeCompleted);
// Here we Set the credentials and the geocode query,which could be an address or location.
findroute.geocodeservice.GeocodeRequest geocodeRequest = new findroute.geocodeservice.GeocodeRequest();
geocodeRequest.Credentials = new Credentials();
geocodeRequest.Credentials.ApplicationId = ((ApplicationIdCredentialsProvider)map1.CredentialsProvider).ApplicationId;
geocodeRequest.Query = strAddress;
// Now Making the asynchronous Geocode request, using the 'waypoint index' as
// the user state to track this request and allow it to be identified when the response is returned.
geocodeService.GeocodeAsync(geocodeRequest, waypointIndex);
}
Step 11 : Now in order
to store the result in to a variable which could be used later to calculate
route between two points and this variable is declared as of internal type.
internal geocodeservice.GeocodeResult[] geocodeResults;
Step 12 : Now we define another Private type method to act as a callback method to calculate the route.
private void geocodeService_GeocodeCompleted(object sender, geocodeservice.GeocodeCompletedEventArgs e)
{
// Retrieve the user state of this response (the 'waypoint index') to identify which geocode request it corresponds to
int waypointIndex = System.Convert.ToInt32(e.UserState);
// Retrieve the GeocodeResult for this response and store it in the global variable geocodeResults, using
// the waypoint index to position it in the array.
geocodeResults[waypointIndex] = e.Result.Results[0];
// Look at each element in the global gecodeResults array to figure out if more geocode responses still
// need to be returned.
bool doneGeocoding = true;
foreach (geocodeservice.GeocodeResult gr in geocodeResults)
{
if (gr == null)
{
doneGeocoding = false;
}
}
// If the geocodeResults array is totally filled, then calculate the route.
if (doneGeocoding)
CalculateRoute(geocodeResults);
}
Step 13 : Now we define another private type method to request for the geocode of the locations provided by the user i.e "From" and "To" point locations in the map:
private void calculate_Click(object sender, RoutedEventArgs e)
{
//Initialize the length of the results array. In this sample we have two waypoints.
geocodeResults = new geocodeservice.GeocodeResult[2];
// Make the two Geocode requests using the values of the text boxes. Also pass the waypoint indexes
// of these two values within the route.
Geocode(fromtxtbx.Text, 0);
Geocode(totxtbx.Text, 1);
}
Step 14 :
Now we have to calculate the route between the two points. In this method we
first create the
service variable and set the callback method using the CalculateRouteCompleted
property, then set a token to validate the credentiality of the map, so here
again you have to enter the credential key of the map.
private void CalculateRoute(geocodeservice.GeocodeResult[] results)
{
routeservice.RouteServiceClient
routeService = new routeservice.RouteServiceClient("BasicHttpBinding_IRouteService");
routeService.CalculateRouteCompleted += new
EventHandler<routeservice.CalculateRouteCompletedEventArgs>(routeService_CalculateRouteCompleted);
// Set the token.
routeservice.RouteRequest
routeRequest = new routeservice.RouteRequest();
routeRequest.Credentials = new
Credentials();
routeRequest.Credentials.ApplicationId = "ENTER THE
CREDENTIAL KEY HERE";
// Return the route points so the
route can be drawn.
routeRequest.Options = new routeservice.RouteOptions();
routeRequest.Options.RoutePathType
= routeservice.RoutePathType.Points;
// Set the waypoints of the route to
be calculated using the Geocode Service results stored in the geocodeResults
variable.
routeRequest.Waypoints = new
System.Collections.ObjectModel.ObservableCollection<routeservice.Waypoint>();
foreach (geocodeservice.GeocodeResult
result in results)
{
routeRequest.Waypoints.Add(GeocodeResultToWaypoint(result));
}
// Make the CalculateRoute
asnychronous request.
routeService.CalculateRouteAsync(routeRequest);
}
Step 15 : Now here comes the interesting part where we know the way points between the two locations and then using this data we mark route between these points. Look at the code below.
private routeservice.Waypoint GeocodeResultToWaypoint(geocodeservice.GeocodeResult result)
{
routeservice.Waypoint
waypoint = new routeservice.Waypoint();
waypoint.Description = result.DisplayName;
waypoint.Location
= new Location();
waypoint.Location.Latitude = result.Locations[0].Latitude;
waypoint.Location.Longitude = result.Locations[0].Longitude;
return waypoint;
}
Step 16 :
Now this is a very important part of the whole project where we locate the points,
use the calculated the distance between these points, the waypoints between
these points and then finally draw a polyline between these points to denote the
route from start position to the end position. Here we use the map layering
in which to draw the route
and then add the route
line to the new layer. We also use a rectangle
which encompasses the route. This is used later to set the map view. Through
this rectangle we calculate all the possible geocode positions of the points
i.e. east, west, north, south, centre. Then for each geocode result (which
are the waypoints of the route), draw a dot on the map using ellipse property.
Finally set the map view using the rectangle which bounds the rendered route.
Also set the center and zoomlevel of the location on the map.
private
void routeService_CalculateRouteCompleted(object
sender, routeservice.CalculateRouteCompletedEventArgs
e)
{
// If the route calculate was a
success and contains a route, then draw the route on the map.
if ((e.Result.ResponseSummary.StatusCode ==
routeservice.ResponseStatusCode.Success) & (e.Result.Result.Legs.Count
!= 0))
{
//
Set properties of the route line you want to draw.
Color routeColor =
Colors.Blue;
SolidColorBrush routeBrush =
new
SolidColorBrush(routeColor);
MapPolyline routeLine =
new MapPolyline();
routeLine.Locations = new
LocationCollection();
routeLine.Stroke = routeBrush;
routeLine.Opacity = 0.50;
routeLine.StrokeThickness = 5.0;
// Retrieve the route points that
define the shape of the route.
foreach (Location
p in e.Result.Result.RoutePath.Points)
{
routeLine.Locations.Add(new
Location { Latitude = p.Latitude, Longitude
= p.Longitude });
}
// Add a map layer in which to draw the route.
MapLayer myRouteLayer =
new MapLayer();
map1.Children.Add(myRouteLayer);
// Add the route line to the new
layer.
myRouteLayer.Children.Add(routeLine);
// Figure the rectangle which
encompasses the route. This is used later to set the map view.
double centerlatitude =
(routeLine.Locations[0].Latitude + routeLine.Locations[routeLine.Locations.Count
- 1].Latitude) / 2;
double centerlongitude =
(routeLine.Locations[0].Longitude +
routeLine.Locations[routeLine.Locations.Count - 1].Longitude) / 2;
Location centerloc =
new Location();
centerloc.Latitude
= centerlatitude;
centerloc.Longitude = centerlongitude;
double north, south, east, west;
if ((routeLine.Locations[0].Latitude > 0) && (routeLine.Locations[routeLine.Locations.Count
- 1].Latitude > 0))
{
north = routeLine.Locations[0].Latitude > routeLine.Locations[routeLine.Locations.Count - 1].Latitude ? routeLine.Locations[0].Latitude : routeLine.Locations[routeLine.Locations.Count - 1].Latitude;
south = routeLine.Locations[0].Latitude < routeLine.Locations[routeLine.Locations.Count - 1].Latitude ? routeLine.Locations[0].Latitude : routeLine.Locations[routeLine.Locations.Count - 1].Latitude;
}
else
{
north = routeLine.Locations[0].Latitude < routeLine.Locations[routeLine.Locations.Count - 1].Latitude ? routeLine.Locations[0].Latitude : routeLine.Locations[routeLine.Locations.Count - 1].Latitude;
south = routeLine.Locations[0].Latitude > routeLine.Locations[routeLine.Locations.Count - 1].Latitude ? routeLine.Locations[0].Latitude : routeLine.Locations[routeLine.Locations.Count - 1].Latitude;
}
if ((routeLine.Locations[0].Longitude < 0) && (routeLine.Locations[routeLine.Locations.Count - 1].Longitude < 0))
{
west = routeLine.Locations[0].Longitude < routeLine.Locations[routeLine.Locations.Count - 1].Longitude ? routeLine.Locations[0].Longitude : routeLine.Locations[routeLine.Locations.Count - 1].Longitude;
east = routeLine.Locations[0].Longitude > routeLine.Locations[routeLine.Locations.Count - 1].Longitude ? routeLine.Locations[0].Longitude : routeLine.Locations[routeLine.Locations.Count - 1].Longitude;
}
else
{
west = routeLine.Locations[0].Longitude > routeLine.Locations[routeLine.Locations.Count - 1].Longitude ? routeLine.Locations[0].Longitude : routeLine.Locations[routeLine.Locations.Count - 1].Longitude;
east = routeLine.Locations[0].Longitude < routeLine.Locations[routeLine.Locations.Count - 1].Longitude ? routeLine.Locations[0].Longitude : routeLine.Locations[routeLine.Locations.Count - 1].Longitude;
}
// For each geocode result (which are the waypoints of the route), draw a dot on the map.
foreach (geocodeservice.GeocodeResult gr in geocodeResults)
{
Ellipse point = new Ellipse();
point.Width = 10;
point.Height = 10;
point.Fill = new SolidColorBrush(Colors.Red);
point.Opacity = 0.65;
location.Latitude = gr.Locations[0].Latitude;
location.Longitude = gr.Locations[0].Longitude;
MapLayer.SetPosition(point, location);
MapLayer.SetPositionOrigin(point, PositionOrigin.Center);
// Add the drawn point to the route layer.
myRouteLayer.Children.Add(point);
}
// Set the map view using the rectangle which bounds the rendered route.
double latitude = 0.0;
double longtitude = 0.0;
map1.SetView(location, 12);
map1.Center = location;
GeoCoordinate CurrentLocCoordinate = new System.Device.Location.GeoCoordinate(latitude, longtitude);
}
}
Step 17 : To manually change the zoom level of the map we add two buttons for serving this purpose.
private
void button2_Click(object
sender, RoutedEventArgs e)
{
double zoom;
zoom = map1.ZoomLevel;
map1.ZoomLevel = ++zoom;
}
private void button3_Click(object sender, RoutedEventArgs e)
{
double zoom;
zoom = map1.ZoomLevel;
map1.ZoomLevel = --zoom;
}
Step 18 :
Add a button named as "view" having the content "Change
view" to change the view of the map from Aerial to Road mode. On the click event
of this button write the following code.
private void view_Click(object sender, RoutedEventArgs e)
{
if (map1.Mode is RoadMode)
{
map1.Mode = new AerialMode(true);
}
else
{
map1.Mode = new RoadMode();
}
}
Step 19 : Now debug the project and see the following output. Initially the view of the map is Aerial Mode.

Now changing the view of the map to Road Mode.

Now enter the locations between which the route is found.

The route in Road mode view is.

The route in Road mode view is.

Hope you would have enjoyed working this project. Do provide your feedback.

mukasa ronaldPosted Jul 24, 2015, 5:55 AM
this was helpful them how can i use this very code to return the distance of the distance covered?
Markus TenghamnPosted Apr 30, 2013, 8:49 PM
If you are having the findroute issue then change findroute to your project name.
sasa sasaPosted Nov 30, 2012, 7:46 PM
THat's great article. BTW in this article we send string address to find location. For example if I have two locations how can i get it work with this example?
tfruazenPosted Aug 11, 2012, 10:36 AM
am getting error at findroute namespace how to solve tha?
Hai Luong SonPosted Jul 18, 2012, 1:53 AM
thank to much! moa moa!
Hai Luong SonPosted Jul 18, 2012, 1:52 AM
project is a great.thanks
eslam elshemiPosted Jun 28, 2012, 9:56 PM
great , but i need to draw all possible routes between two location on Bing map
Abhinav MaheshwariPosted Jun 23, 2012, 6:34 AM
Excellent article Manoj, saved me a lot of time. Can you please explain how does the bounding of route work in step 16, since you are not using the east/west/north/south.
aykutucarPosted Jun 3, 2012, 10:41 PM
that was very descriptive and helpful, saved me a lot of time. thank you!
Saikat PanPosted May 20, 2012, 9:52 AM
I implemented the same code and was trying to find a particular address, something like this: geocodeRequest.Query = "R.K.Cineplex,Road No.2,Banjara Hills,Hyderabad-500034"; The GeocodeResult object is returnng null,means to record is found. Is there anything wrong I am doing? Please help. Thanks
jawad awawdehPosted Apr 16, 2012, 5:45 PM
very very good article ... thanx i try to implement this project but i have this errors : *The type or namespace name 'findroute' could not be found (are you missing a using directive or an assembly reference?) *The name 'location' does not exist in the current context please i need help .... it's important to my graduation project ...
mohammed badwanPosted Apr 7, 2012, 4:01 PM
using findroute.geocodeservice; is showing error what is the problem the error is type using findroute.geocodeservice; couldn't be found help me please
Kenpro RainpowPosted Mar 26, 2012, 10:18 PM
thanks so much .
Tung NguyenPosted Mar 24, 2012, 6:22 AM
Thank you so much ! That helps me a lot.
HECQUET JeaneditedPosted Jan 24, 2012, 6:26 AMEdited Jan 25, 2012, 3:08 AM
If the destination is unknown = crash sample Hôtel de ville , 34304 Apart from this annoying bug the program is super Thank you My email [email protected]
asim abbaseditedPosted Jan 18, 2012, 10:13 AMEdited Jan 18, 2012, 10:14 AM
well done good work i need more help from you i need to make an application which show the distance between two points in location and also show the popular places means hotels,hospitals etc in the place where the route is draw thanks in advance i am waiting from your reply my email id is: [email protected]