Before reading this article, I highly recommend reading the following previous parts:
Introduction
We continue our path of Geolocation Services, but first let's see at a glance what you have learned in the previous article. Placeholderswere were explained, also how to define, create and then superimpose the control NokiaMaps, but starting from the installation of the Phone Toolkit and the need to be able to use them. Later, with the control pushpin, they were defined for displaying the user's location and for the signaling of multiple points of interest. Finally, we made a brief overview of what a UserLocationMarker control is, also part of Phone Toolkit. This article shows how to view a route on the map and how to calculate a route and manage the privacy policy on the user's location. We will see the following in the following order:
- Introduction to Class RouteQuery
- Implementation of the class RouteQuery in test project
- Test the application
- Privacy policy
- Conclusion
- Other Resources
Remember to use the services of geolocation and maps; you must enable the capability ID_CAP_LOCATION and ID_CAP_MAP, discussed in previous articles. To be found in the file WMAppManifest.xml in the Features section.
Introduction to the class RouteQuery
In an application that uses Geolocation Services and in this case a control NokiaMaps, you cannot miss the opportunity to track and view a route within that control. For this reason, Windows Phone Silverlight provides developers the RouteQuery class, with which it is possible to draw and display a path from a starting position to an arrival. Now let's see the main methods, properties and events that expose this class.
Properties
- TravelMode
- RouteOptimization
- Waypoints
TravelMode: This how to view the map, we can choose between two available values exposed enumerator TravelMode. Driving when we are traveling by car, walking or suitable if we walk.
RouteOptimization: in this case, we have the opportunity to choose between two values enumerators, RouteOptimization and MinimizeTime, with which the route calculation is performed based on time or MinimizeDistance if we run the route calculation based on distance.
Waypoints: it is a collection of type GeoCoordinates, accounting or points of the route displayed on the map. It can enter all the necessary points that will then be displayed in the order they were entered.
Methods
- QueryAsinc()
QueryAsync(): This method simply does the calculation of the points on the property Waypoints.
Events
- QueryCompleted
QueryCompleted: this event, will be performed when the method QueryAsync() completes the calculation for tracing the route on the map. It will return an object of type MapRoute with all the necessary data to show the location on the control NokiaMaps.
Implementation of the class RouteQuery in test project
After this brief introduction, let's see how you can view a route from a starting point (our position) to a point of arrival. First we take over the project that we used in the second part on the control NokiaMaps. Find the complete example at this link. We open the project and explore the solutions. We place the cursor on the project name, click the right mouse button and choose "Add" and immediately after that "New Item". From the available templates select "Page vertical Windows Phone" and call it RouteTravel. Remaining in the file.xaml insert the following code to define the graphical interface. The two namespaces are necessary for using the monitoring and control NokiaMaps Pushpin.
- xmlns:Controls="clr-namespace:Microsoft.Phone.Maps.Controls;assembly=Microsoft.Phone.Maps"
- xmlns:toolkit="clr-namespace:Microsoft.Phone.Maps.Toolkit;assembly=Microsoft.Phone.Controls.Toolkit"
The remaining part of code to the graphical interface.
-
- <Grid x:Name="LayoutRoot" Background="Transparent">
- <Grid.RowDefinitions>
- <RowDefinition Height="Auto"/>
- <RowDefinition Height="*"/>
- </Grid.RowDefinitions>
-
-
- <StackPanel Grid.Row="0" Margin="12,17,0,28">
- <TextBlock Text="GeoPositionSample" Style="{StaticResource PhoneTextNormalStyle}"/>
- <TextBlock Text="Route travel" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
- </StackPanel>
-
-
- <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
- <Grid.RowDefinitions>
- <RowDefinition Height="Auto"/>
- <RowDefinition Height="*"/>
- <RowDefinition Height="Auto"/>
- </Grid.RowDefinitions>
-
- <Grid Grid.Row="0">
- <Grid.RowDefinitions>
- <RowDefinition Height="Auto"/>
- <RowDefinition Height="Auto"/>
- </Grid.RowDefinitions>
-
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="Auto"/>
- <ColumnDefinition Width="Auto"/>
- <ColumnDefinition Width="Auto"/>
- </Grid.ColumnDefinitions>
-
- <TextBlock Grid.Row="0" Grid.Column="0" Text="From" VerticalAlignment="Center"/>
- <TextBox x:Name="tbxFrom" Text="My Position" IsEnabled="False" TextAlignment="Center" Grid.Row="0" Grid.Column="2" Width="400"/>
-
- <TextBlock Grid.Row="1" Grid.Column="0" Text="To" VerticalAlignment="Center"/>
- <TextBox x:Name="tbxTo" Grid.Row="1" Grid.Column="2" Width="400"/>
- </Grid>
-
- <StackPanel Grid.Row="1">
- <Controls:Map x:Name="mapLocation" Height="442" Width="480">
- <toolkit:MapExtensions.Children>
- <toolkit:Pushpin x:Name="myPushPinStart" Content="your are here" Visibility="Collapsed"/>
- <toolkit:Pushpin x:Name="myPushPinEnd" Content="destination" Visibility="Collapsed"/>
- </toolkit:MapExtensions.Children>
- </Controls:Map>
- </StackPanel>
-
- <Button Grid.Row="2" x:Name="btnFindCoordinate" Content="Find Route" Tap="btnFindCoordinate_Tap"/>
- </Grid>
- </Grid>
If everything has been entered correctly, this will be the appearance of the screen RouteTravel.
Image 1.1 The screen Route travel.Now open the file MyPosition.cs and insert the following code.
- public static void FindRoute(string position, List<double> startposition, Map maps)
- {
- var locator = new Geolocator();
- var geocodequery = new GeocodeQuery();
- var coordinate = new List<GeoCoordinate>();
- var map = maps;
-
-
- if (!locator.LocationStatus.Equals(PositionStatus.Disabled))
- {
- try
- {
- geocodequery.GeoCoordinate = new GeoCoordinate(0, 0);
- geocodequery.SearchTerm = position;
- geocodequery.QueryAsync();
-
- geocodequery.QueryCompleted += (sender, args) =>
- {
- if (!args.Result.Equals(null))
- {
- var result = args.Result.FirstOrDefault();
- coordinate.Add(new GeoCoordinate(startposition[0],startposition[1]));
- coordinate.Add(new GeoCoordinate(result.GeoCoordinate.Latitude,result.GeoCoordinate.Longitude));
-
-
- var midLatitude = coordinate.Average(a => a.Latitude);
- var midLongitude = coordinate.Average(b => b.Longitude);
- map.Center = new GeoCoordinate(midLatitude, midLongitude);
- map.ZoomLevel = 12;
-
- RouteQuery query = new RouteQuery();
- query.TravelMode = TravelMode.Driving;
- query.RouteOptimization = RouteOptimization.MinimizeTime;
- query.Waypoints = coordinate;
-
- query.QueryCompleted +=(senderone,argsone)=>
- {
- var route = new MapRoute(argsone.Result);
- map.AddRoute(route);
-
- var startpushpin = (Pushpin)maps.FindName("myPushPinStart");
- startpushpin.GeoCoordinate = new GeoCoordinate(startposition[0], startposition[1]);
- startpushpin.Visibility = System.Windows.Visibility.Visible;
-
- var endpushpin = (Pushpin)maps.FindName("myPushPinEnd");
- endpushpin.GeoCoordinate = new GeoCoordinate(coordinate[1].Latitude, coordinate[1].Longitude);
- endpushpin.Visibility = System.Windows.Visibility.Visible;
- };
-
- query.QueryAsync();
- }
- };
- }
-
- catch (Exception ex)
- {
- MessageBox.Show(ex.Message, AppResources.ApplicationTitle, MessageBoxButton.OK);
- }
- }
-
- else
- {
- MessageBox.Show("Service Geolocation not enabled!", AppResources.ApplicationTitle, MessageBoxButton.OK);
- }
- }
Analyze the code and have created a method that requires three parameters, the first of type string that corresponds to the final destination, we're going to enter into the TextBox screen RouteTravel. The second and a collection of type double that represents the coordinates of our current position, the last we have already seen in the previous article, it is avariable of type Maps that does nothing but change the control NokiaMaps we screen and we spend as a reference to the method FindRoute. The additional pieces of code are:
- coordinate.Add(new GeoCoordinate(startposition[0],startposition[1]));
- coordinate.Add(new GeoCoordinate(result.GeoCoordinate.Latitude,result.GeoCoordinate.Longitude));
We value the collection coordinates type GeoCoordinate, with the latitude and longitude contained in the collection StartPosition of type double, if we remember they are the coordinates of our current position and what the second line of code does is to add the coordinates of the place we chose, or the destination, all when the method QueryAsync () class GeocodeQuery finished the conversion from address to coordinates and then signing the event QueryCompleted to get all the necessary data. Whereas the novelty starts from this code.
- RouteQuery query = new RouteQuery();
- query.TravelMode = TravelMode.Driving;
- query.RouteOptimization = RouteOptimization.MinimizeTime;
- query.Waypoints = coordinate;
We declare a new object RouteQuery, we value the properties TravelMode on Driving, RouteOptimization on MinimizeTime and finally we value the property Waypoints with coordinate's collection. Then, we subscribe to the event QueryCompleted exposed by the class RouteQuery.
- query.QueryCompleted +=(senderone,argsone)=>
- {
- var route = new MapRoute(argsone.Result);
- map.AddRoute(route);
-
- var startpushpin = (Pushpin)maps.FindName("myPushPinStart");
- startpushpin.GeoCoordinate = new GeoCoordinate(startposition[0], startposition[1]);
- startpushpin.Visibility = System.Windows.Visibility.Visible;
-
- var endpushpin = (Pushpin)maps.FindName("myPushPinEnd");
- endpushpin.GeoCoordinate = new GeoCoordinate(coordinate[1].Latitude, coordinate[1].Longitude);
- endpushpin.Visibility = System.Windows.Visibility.Visible;
- };
-
- query.QueryAsync();
Here enters a new class, MapRoute that provides everything you need to draw the route on the map and then this class exposes many other properties that will deepen in the next article, for now we need to understand what was said before. To view the route on the map we need this instruction code:
Recalling the method exposed by the control NokiaMaps and passing as a parameter an object of type MapRoute. While this piece of code:
- var startpushpin = (Pushpin)maps.FindName("myPushPinStart");
- startpushpin.GeoCoordinate = new GeoCoordinate(startposition[0], startposition[1]);
- startpushpin.Visibility = System.Windows.Visibility.Visible;
-
- var endpushpin = (Pushpin)maps.FindName("myPushPinEnd");
- endpushpin.GeoCoordinate = new GeoCoordinate(coordinate[1].Latitude, coordinate[1].Longitude);
- endpushpin.Visibility = System.Windows.Visibility.Visible;
There must already be familiar with, does nothing but add two control pushpins on the map, the first enhanced with the coordinates of our position, in other words "myPushPinStart", and one with the coordinates obtained after the execution of the method QueryAsync () exposed by the RouteQuery class, talk about the control "myPushPinEnd". Finally it remains to be recalled, as previously said, that the method QueryAsync() obtains all the information necessary to be used in the control NokiaMaps.
Now open the file RouteTravel.xaml.cs, where we will implement the method FindRoute() just described. What and manage the event and tap the button btnFindCoordinate, where we will call the method, so insert the following code.
- private async void btnFindCoordinate_Tap(object sender, System.Windows.Input.GestureEventArgs e)
- {
- var startPosition = await MyPosition.GetPosition();
- MyPosition.FindRoute(tbxTo.Text, startPosition, mapLocation);
- }
We analyze the preceding code. What the first statement does is call the method GetPosition() asynchronously that you find in the class MyPosition that returns a collection of type double that will contain our current position in latitude and longitude. The second statement, however, implements the method FindRoute(), passing three parameters, the Text property of the TextBox tbxTo that corresponds to the destination that we will enter when running the application, the second parameter and the collection of type double containing the latitude and longitude of our position and the last not more than the reference control MapLocation we pass to the method so that you can then view the route on the map. After this activity and we need one more thing, we open the file MainPage.xaml and insert the following code immediately below the button btnMultiplePushPin:
- <Button x:Name="btnRouteTravel" Content="Route travel" Tap="btnRouteTravel_Tap"/>
Using the F7 key we access the file MainPage.xaml.cs, where we're going to put the management of the event Tap the button btnRouteTravel.
- private void btnRouteTravel_Tap(object sender, System.Windows.Input.GestureEventArgs e)
- {
- NavigationService.Navigate(new Uri("/RouteTravel.xaml", UriKind.Relative));
- }
Test the applicationWe included everything you need to view a route on NokiaMaps control and now to try it out. Press the F5 key and start debugging. This will be the Home screen of the application after adding the new button btnRouteTravel.
Image 1.2 The initial screen with the new button Route travel.
We do a tap on the last button and we will be led to the following screen.
Image 1.3 The screen Route travel when running the application.
The screen consists of two TextBlock controls with values the "Form" (our position), "To" where we will enter the destination you want to view, a control NokiaMaps on which will track the path that we display and finally a button called "Find route" for which a tap will execute the code that we saw earlier. Now we type a location in the TextBox beside the word "To" as shown in the figure.
Image 1.4 The screen Route travel with the destination "Caselle Torinese."
After entering the destination, we tap on the button Find Route and if everything is done correctly, here is what will be the result on the map.
Image 1.5 The screen Route travel with the path displayed on the map.Privacy policyOne very important thing is, if we decide to make use of the maps in our application and in general of Geolocation Services and indeed the user's privacy. And good to know, that the data related to the user's location are sensitive information that, if used improperly, can lead to having problems of no small importance. My advice from a personal point of view is the following:
- Provide a screen (I do not mean the information on the application) that is dedicated only to describe the application that makes use of Geolocation Services and / or maps, describing that data collected are used only for the operation of the application and that are not in any way saved and stored or distributed to third parties.
- Always provide a button on the screen that gives the option to disable Geolocation Services, leading the user to the correct screen shown in the figure.
Image 1.6 The Position screen in Setup.It is true that the user will be warned by a screen asking to accept the conditions laid down on the use of the position, if you decide to download an application from the store that makes use of the Geolocation Services, however to expect this feature, because it requires little time and date the user the ability to turn on and off at any time Geolocation Services.
ConclusionIn this article, it was explained the operation of the class RouteQuery, what are the main methods, properties and events that this class exhibits, we saw how to implement them and later view a route on the map from our location to the final destination, implementing a new class called MapRoute that we will see and describe in the next article. Finally was a brief overview of what a privacy policy is, in other words about things you need to bear in mind when we use the Geolocation Services of maps in our application. In the next article, we will see the class MapRoute, its methods and properties and finally what to do to post on the store application that uses maps.
Other ResourcesAnother important place to find a huge amount of Windows Phone related articles is the TechNet Wiki itself. The best entry point is
Windows Phone Resources on the TechNet Wiki.