Windows Phone 8.1 - Map Control

Introduction

Hello everyone. I hope you're doing great with Windows Phone 8.1. I really love the new features of Windows Phone 8.1. Today I'll talk about Windows Phone Map Control and obviously it's Bing Map. In a new update of Windows Phone, there are significant APIs changed from the previous Windows Phone 8.0. Many great features were addedm like Geofencing. So let's get cracking with the entirely new Windows Phone 8.1 Map Control.

Creating a New Project and Add a Map Control

Create a new project and provide it a name (simply “Map” or whatever you want). Now, we'll add our Map Control from the “Toolbox”. Drag the “MapContol” tool from the “Toolbox” and place it in the main Grid.

mapControl
                           Figure 1

Making Grids

We'll now modify our main Grid to re-size the “MapControl” and to show some other stuffs. First of all, we'll make some rows for other controls.

  1. <Grid HorizontalAlignment="Stretch"  
  2.                 Margin="8,8,8,8" VerticalAlignment="Stretch">  
  3.     <Grid.RowDefinitions>  
  4.         <RowDefinition Height="10"/>  
  5.         <RowDefinition Height="50"/>  
  6.         <RowDefinition Height="*"/>  
  7.         <RowDefinition Height="40"/>  
  8.     </Grid.RowDefinitions>  
  9.     ...  
  10. </Grid>  
Listing 1

Here, in line numbers 4, 5, 6 and 7 we've declared four “RowDefinitions”. The first one is 10px in height, the second 50px, the third one is “*” that will cover the rest of the grid space and the last one is 40px.

Adding Controls

Here are the controls we've used in our “MainPage.xaml”.
  1. <Canvas>  
  2.     <ProgressBar x:Name="progressBar" Grid.Row="0"  
  3.                  IsIndeterminate="True"  
  4.                  Maximum="100" Value="30"  
  5.                  Height="10"  
  6.                  Width="400"/>  
  7. </Canvas>  
  8.   
  9. <TextBlock TextWrapping="NoWrap" Grid.Row="1"  
  10.            Text="Map control"  
  11.            FontSize="36"  
  12.            Margin="8,0,0,16" />  
  13. <Maps:MapControl x:Name="MyMap" Grid.Row="2"  
  14.                     HorizontalAlignment="Left"  
  15.                     VerticalAlignment="Top"  
  16.                     Height="500"  
  17.                     Width="385"  
  18.                  MapTapped="MyMap_MapTapped" />  
  19. <Slider x:Name="mySlider" Grid.Row="3"  
  20.         Maximum="20"  
  21.         Minimum="10"  
  22.         ValueChanged="Slider_ValueChanged" />  
Listing 2

We've used a “ProgressBar” control, to indicate when the Map is loading, a “TextBlock” to show the title, a “MapControl” to show the Bing Map and a “Slider” to zoom in and zoom out.

Adding AppBar

We've also used a “BottomAppBar” to locate your current position.
  1. <Page.BottomAppBar>  
  2.     <CommandBar ClosedDisplayMode="Minimal" Opacity="0.5">  
  3.         <AppBarButton Label="locate me" Icon="Target" Click="LocateMe_Click" />  
  4.     </CommandBar>  
  5. </Page.BottomAppBar>  
Listing 3

I'm not going into the details of adding controls and how they work, if you don't know please feel free to have a look at my previous articles.

So, finally our design will look like this.

map control
                           Figure 2

Code Behind

It is now time to do the code behind in C#. Let's open “MainPage.xaml.cs” and find the “OnNavigatedTo” method. Modify it as in the following.
  1. public sealed partial class MainPage : Page  
  2. {  
  3.     Geolocator geolocator;  
  4.     protected async override void OnNavigatedTo(NavigationEventArgs e)  
  5.     {  
  6.         // Map Token for testing purpose,   
  7.         // otherwise you'll get an alart message in Map Control  
  8.         MyMap.MapServiceToken = "abcdef-abcdefghijklmno";  
  9.    
  10.         geolocator = new Geolocator();  
  11.         geolocator.DesiredAccuracyInMeters = 50;  
  12.    
  13.         try  
  14.         {  
  15.             // Getting Current Location  
  16.             Geoposition geoposition = await geolocator.GetGeopositionAsync(  
  17.                 maximumAge: TimeSpan.FromMinutes(5),  
  18.                 timeout: TimeSpan.FromSeconds(10));  
  19.    
  20.             MapIcon mapIcon = new MapIcon();  
  21.             // Locate your MapIcon  
  22.             mapIcon.Image = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Assets/my-position.png"));  
  23.             // Show above the MapIcon  
  24.             mapIcon.Title = "Current Location";  
  25.             // Setting up MapIcon location  
  26.             mapIcon.Location = new Geopoint(new BasicGeoposition()  
  27.             {  
  28.                 //Latitude = geoposition.Coordinate.Latitude, [Don't use]  
  29.                 //Longitude = geoposition.Coordinate.Longitude [Don't use]  
  30.                 Latitude = geoposition.Coordinate.Point.Position.Latitude,  
  31.                 Longitude = geoposition.Coordinate.Point.Position.Longitude  
  32.             });  
  33.             // Positon of the MapIcon  
  34.             mapIcon.NormalizedAnchorPoint = new Point(0.5, 0.5);  
  35.             MyMap.MapElements.Add(mapIcon);  
  36.             // Showing in the Map  
  37.             await MyMap.TrySetViewAsync(mapIcon.Location, 18D, 0, 0, MapAnimationKind.Bow);  
  38.                
  39.             // Disable the ProgreesBar  
  40.             progressBar.Visibility = Windows.UI.Xaml.Visibility.Collapsed;  
  41.             // Set the Zoom Level of the Slider Control  
  42.             mySlider.Value = MyMap.ZoomLevel;  
  43.         }  
  44.         catch (UnauthorizedAccessException)  
  45.         {  
  46.             MessageBox("Location service is turned off!");  
  47.         }  
  48.         base.OnNavigatedTo(e);  
  49.     }  
  50. ...  
  51. }  
Listing 4

Our main work is done, now we are ready to write the other methods for it to work perfectly.
  1. // Slider Control  
  2. private void Slider_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)  
  3. {  
  4.     if (MyMap != null)  
  5.         MyMap.ZoomLevel = e.NewValue;  
  6. }  
  7.   
  8. // Locate Me Bottom App Bar  
  9. private async void LocateMe_Click(object sender, RoutedEventArgs e)  
  10. {  
  11.     progressBar.Visibility = Windows.UI.Xaml.Visibility.Visible;  
  12.     geolocator = new Geolocator();  
  13.     geolocator.DesiredAccuracyInMeters = 50;  
  14.   
  15.     try  
  16.     {  
  17.         Geoposition geoposition = await geolocator.GetGeopositionAsync(  
  18.             maximumAge: TimeSpan.FromMinutes(5),  
  19.             timeout: TimeSpan.FromSeconds(10));  
  20.         await MyMap.TrySetViewAsync(geoposition.Coordinate.Point, 18D);  
  21.         mySlider.Value = MyMap.ZoomLevel;  
  22.         progressBar.Visibility = Windows.UI.Xaml.Visibility.Collapsed;  
  23.     }  
  24.     catch (UnauthorizedAccessException)  
  25.     {  
  26.         MessageBox("Location service is turned off!");  
  27.     }  
  28. }  
  29.   
  30. // Custom Message Dialog Box  
  31. private async void MessageBox(string message)  
  32. {  
  33.     var dialog = new MessageDialog(message.ToString());  
  34.     await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () => await dialog.ShowAsync());  
  35. }  
Listing 5

Adding Tap Event

One more thing I'd like to add is Map Tapped functionality. We'll add another method that will provide us a cool feature when we tap somewhere and in the Map Icon. It'll show the location details in the Message Dialog Box.

To add this method, go to “MainPage.xaml”, select “MapControl” in the main grid. If you don't see the “Properties” tab, then hit F4 and you'll find it on the left side of Visual Studio.

Now double-click on the “MapTapped” section and it'll automatically generate the method stub for you.

properties
                                                      Figure 3

Now complete the “MyMap_MapTapped” method in the “MainPage.xaml.cs”
  1. private async void MyMap_MapTapped(MapControl sender, MapInputEventArgs args)  
  2. {  
  3.     Geopoint pointToReverseGeocode = new Geopoint(args.Location.Position);  
  4.    
  5.     // Reverse geocode the specified geographic location.  
  6.     MapLocationFinderResult result =  
  7.         await MapLocationFinder.FindLocationsAtAsync(pointToReverseGeocode);  
  8.    
  9.     var resultText = new StringBuilder();  
  10.    
  11.     if (result.Status == MapLocationFinderStatus.Success)  
  12.     {  
  13.         resultText.AppendLine(result.Locations[0].Address.District + ", " + result.Locations[0].Address.Town + ", " + result.Locations[0].Address.Country);  
  14.     }  
  15.    
  16.     MessageBox(resultText.ToString());  
  17. }  
Listing 6

Adding Location Capability

Our work is now done, but if you run the application in your device or emulator, you'll definitely get an error. Because we've given permission to track our current position to our application. To do this, go to “Package.appxmanifest” and find the “Capabilities” section and tick the “Location” service and save it.

Adding Location Capability
                                                                              Figure 4

Running the Application

Now if you run the application it'll look exactly like this.

Running the Application

If you tap on the “MapIcon” it'll show the location details on the Message Dialog Box.

Using Polygon for Pushpin

Another thing is, if don't want to use an external image as a “MapIcon” then you can use a custom “Pushpin” like a “Polygon” control. Then you only need to modify the “OnNavigatedTo” method like this:
  1. protected async override void OnNavigatedTo(NavigationEventArgs e)  
  2. {  
  3.     // Map Token for testing purpose,   
  4.     // otherwise you'll get an alart message in Map Control  
  5.     MyMap.MapServiceToken = "abcdef-abcdefghijklmno";  
  6.    
  7.     geolocator = new Geolocator();  
  8.     geolocator.DesiredAccuracyInMeters = 50;  
  9.    
  10.     try  
  11.     {  
  12.         // Getting Current Location  
  13.         Geoposition geoposition = await geolocator.GetGeopositionAsync(  
  14.             maximumAge: TimeSpan.FromMinutes(5),  
  15.             timeout: TimeSpan.FromSeconds(10));  
  16.            
  17.         // Create a New Pushpin  
  18.         var pushpin = CreatePushPin();  
  19.         MyMap.Children.Add(pushpin);  
  20.         // Setting up Pushpin location  
  21.         var location = new Geopoint(new BasicGeoposition()  
  22.         {  
  23.             Latitude = geoposition.Coordinate.Latitude,  
  24.             Longitude = geoposition.Coordinate.Longitude  
  25.         });  
  26.         MapControl.SetLocation(pushpin, location);  
  27.         // Position of the Pushpin  
  28.         MapControl.SetNormalizedAnchorPoint(pushpin, new Point(0.0, 1.0));  
  29.         // Showing in the Map  
  30.         await MyMap.TrySetViewAsync(location, 18D, 0, 0, MapAnimationKind.Bow);  
  31.            
  32.         // Disable the ProgressBar  
  33.         progressBar.Visibility = Windows.UI.Xaml.Visibility.Collapsed;  
  34.         // Set the Zoom Level of the Slider Control  
  35.         mySlider.Value = MyMap.ZoomLevel;  
  36.     }  
  37.     catch (UnauthorizedAccessException)  
  38.     {  
  39.         MessageBox("Location service is turned off!");  
  40.     }  
  41.     base.OnNavigatedTo(e);  
  42. }  
Listing 7

And the “CreatePushPin” method is given below.
  1. private DependencyObject CreatePushPin()  
  2. {  
  3.     // Creating a Polygon Marker  
  4.     Polygon polygon = new Polygon();  
  5.     polygon.Points.Add(new Point(0, 0));  
  6.     polygon.Points.Add(new Point(0, 50));  
  7.     polygon.Points.Add(new Point(25, 0));  
  8.     polygon.Fill = new SolidColorBrush(Colors.Red);  
  9.    
  10.     // Return the Polygon Marker  
  11.     return polygon;  
  12. }  
Listing 8

Running the Application

Now, if you run the application, the marker will look like this.

output
                           Figure 6

Map Overlaying

It’s really cool and awesome using a custom Pushpin in Windows Phone 8.1. One more thing I’d like to add is overlaying tiled images on a map. If you want to overlay third-party or custom tiled images on the map and make it customized, then you simply need to use the following lines of code in the “OnNavigatedTo” method at the top.
  1. protected async override void OnNavigatedTo(NavigationEventArgs e)  
  2. {  
  3.     var httpsource = new HttpMapTileDataSource("http://a.tile.openstreetmap.org/{zoomlevel}/{x}/{y}.png");  
  4.     var ts = new MapTileSource(httpsource);  
  5.     MyMap.TileSources.Add(ts);  
  6. ...  
  7.     base.OnNavigatedTo(e);  
  8. }  
Listing 9

And if your run the application, it will provide you a much more graphical view than before with some details.

graphical view
                           Figure 7

Summary

And that’s it! I hope you understand how to use the “MapControl” in Windows Phone 8.1. Have fun with the Map Control and make some cool applications with it. Read more about Maps and directions (XAML) at: http://bit.ly/X7S7ei

I will be here with a new topic soon. Until then good bye. Have a nice day.

Happy Coding!

Read the original article at: bit.ly/1D6O93Q