The Nokia Maps on Windows Phone 8: Part 1

Introduction

We continue our journey with geolocation services, but before we will review what has been learned so far. We started with the first article, that you can find at this link that addressed in detail everything about the Geolocator. We've seen how geolocation services can be enabled to receive data on the user's location and how to get the latitude and longitude coordinates. Subsequently, we delved into the ReverseGeocodeQuery class to convert latitude and longitude coordinates in an address, for those who have not had a chance to read its content it can be done by accessing this link. In the next article, we have explored the GeocodeQuery class, similar to ReverseGeocodeQuery, that has the difference that in this case, we're going to convert an address into latitude and longitude coordinates. Here's the link for those who haven't had the opportunity to read it. After this brief introduction, we continue our journey, we will talk and we will study ways to operate the control's main Nokia Maps available since version 8.0 for Windows Phone in three different articles. In this we will study ways of functioning of the control.

Control Nokia Maps

Up to version seven of Windows Phone, geolocation services were managed with the famous Bing Maps. Windows Phone 8 introduced mapping services from Nokia. This means having an application preinstalled on the phone, with which you can buy our application, interact to calculate a route, show a place on the map, all using the Map Direction Task Launcher and Maps Task. We have, however, a new control that allows us greater customization, that we can include in our application, without the need to activate a Launcher, control Nokia Maps.

Control Nokia Maps offers various scenarios that we can implement within our application, a classic example is to calculate a route displayed on the map, but we see the main features in addition to the one just described.

  • ZoomLevel
  • Types of map display
  • Other properties
  • Manage multiple levels

ZoomLevel

This property allows you to enlarge or decrease the scale factor of the map, with values ranging from 1 (lowest) to 19 (maximum), all acting on the property ZoomLevel exposed by the control. Interacting with this property is remarkably simple, let's look at this piece of code.

  1. namespace GeoPositionSample  
  2. {  
  3.     public partial class ZoomLevel : PhoneApplicationPage  
  4.     {  
  5.         public ZoomLevel()  
  6.         {  
  7.             InitializeComponent();  
  8.         }  
  9.   
  10.         private void btnZoomLevelPlus_Tap(object sender, System.Windows.Input.GestureEventArgs e)  
  11.         {  
  12.             if(mapLocation.ZoomLevel <= 19)  
  13.             {  
  14.                 mapLocation.ZoomLevel += 1;  
  15.             }  
  16.         }  
  17.   
  18.         private void btnZoomLevelMinus_Tap(object sender, System.Windows.Input.GestureEventArgs e)  
  19.         {  
  20.             if(mapLocation.ZoomLevel > 1)  
  21.             {  
  22.                 mapLocation.ZoomLevel -= 1;  
  23.             }  
  24.         }  
  25.     }  
  26. }  
In the first case, we will increase the value of the property with ZoomLevel + = 1. This means that the value will be increased by one at each tap on the button btnZoomLevelPlus, at the same time enlarging the scale factor of the map and the display accordingly to the inside, while in the second case it reduces the value to up to the minimum zoom, but here is how it looks in our application initially.

home screen of the application
Image 1.1 The home screen of the application.

Map after the tap button btnZoonLevelPuls
Image 1.2 Map after the tap button btnZoonLevelPuls.

Map after the tap button btnZoonLevelMinus
Image 1.3 Map after the tap button btnZoonLevelMinus.

We note that the scale factor of the map has three views, the first image is the default, the second image is referred to as the user performs a tap on the button btnZoonLevelPuls, while the last is done when a tap on the button btnZoomLevelMinus provided map with the initial display (refer image 1.1).

Types of map display

I also remember that the initial view of the maps by default is set to the type of road maps, but you can set four other views in the order: 
  • Aerial: It is a display equal to Hibrid, then display with real things, but no directions.

  • Hybrid: As the type of Aerial, but in this case with directions, routes, points of interest and more.

  • Road (by default): This type of display is the one that we will have a traditional navigation system.

  • Terrain: In this case, we will have the directions, but this type of mapping is useful when we walk in search of a point of interest or destination.

To change the display, you need to value the property CartographicMode with one of the values given above; we find all values in the enumerator MapCartograpichMode, part of the namespace Microsoft.Phone.Maps.Controls. The following is an example of code with which we will be able to tap each button. The button btnCartograpichMode displays the types of mapping available.

  1. int cartograpichMode = 0;   
  2.   
  3. private void btnCartograpichMode_Tap(object sender, System.Windows.Input.GestureEventArgs e)  
  4. {  
  5.    if(cartograpichMode.Equals(4))  
  6.    {  
  7.       cartograpichMode = 1;  
  8.    }  
  9.   
  10.    else  
  11.    {  
  12.       cartograpichMode += 1;  
  13.    }  
  14.   
  15.    switch(cartograpichMode)  
  16.    {  
  17.       case 1:  
  18.       mapLocation.CartographicMode = MapCartographicMode.Aerial;  
  19.       break;  
  20.   
  21.       case 2:  
  22.       mapLocation.CartographicMode = MapCartographicMode.Hybrid;  
  23.       break;  
  24.   
  25.       case 3:  
  26.       mapLocation.CartographicMode = MapCartographicMode.Road;  
  27.       break;  
  28.   
  29.       case 4:  
  30.       mapLocation.CartographicMode = MapCartographicMode.Terrain;  
  31.       break;  
  32.    }  
  33. }  
In the previous example code, we're going to increase the value of the variable cartograpichMode in steps of one and the switch construct whichever is acquired; you will see a different cartographic visualization. The following are the pictures we have on our phone for all four conditions.

The Map in Aerial mode
Image 1.4 The Map in Aerial mode.

The map so Hybrid
Image 1.5 The map so Hybrid.

The Map in Road mode
Image 1.6 The Map in Road mode.

The map so Terrain
Image 1.7 The map so Terrain.

Additional property

Beyond what has been seen so far, there are other important properties with which they can further customize the map and provide the user a pleasant experience. This is exactly: 
  • Heading: with this property we will be able to rotate the map location of the center. It is enhanced with a value of type double.

  • Pitch: This property represents the height of the map from the horizon. Also in this case, the property requires a numerical value of type double.

  • ColorMode: we can set two possible values, Light and Dark, the first suitable during the day, so with higher brightness, the second is suitable instead in low light conditions, such as an overnight trip, this property is of type bool, then the possible values are True or False.

  • LandmarskEnabled: This property allows a 3D visualization of a few points of interest on the map, setting it to True, some elements such as historic buildings, museums and churches will have a display of three-dimensional type.

  • PedestrianFeaturesEnabled: this type of property if set to True, activate map services useful and appropriate if we walk.

Here is how to set the values of these five properties.

  1. public partial class OtherProperties : PhoneApplicationPage  
  2. {  
  3.     bool colorMode;  
  4.     bool landmarksEnabled;  
  5.     bool pedestrianFeaturesEnabled;  
  6.   
  7.   
  8.     public OtherProperties()  
  9.     {  
  10.         InitializeComponent();             
  11.     }  
  12.   
  13.     private void btnHeading_Tap(object sender, System.Windows.Input.GestureEventArgs e)  
  14.     {  
  15.         mapLocation.Heading += 1 ;  
  16.     }  
  17.   
  18.     private void btnPitch_Tap(object sender, System.Windows.Input.GestureEventArgs e)  
  19.     {  
  20.         mapLocation.Pitch += 1;  
  21.     }  
  22.   
  23.     private void btnColorMode_Tap(object sender, System.Windows.Input.GestureEventArgs e)  
  24.     {  
  25.         if(colorMode.Equals(false))  
  26.         {  
  27.             mapLocation.ColorMode = Microsoft.Phone.Maps.Controls.MapColorMode.Dark;  
  28.             colorMode = true;  
  29.         }  
  30.   
  31.         else  
  32.         {  
  33.             mapLocation.ColorMode = Microsoft.Phone.Maps.Controls.MapColorMode.Light;  
  34.             colorMode = false;  
  35.         }  
  36.     }  
  37.   
  38.     private void btnLandmarskEnabled_Tap(object sender, System.Windows.Input.GestureEventArgs e)  
  39.     {  
  40.         if(landmarksEnabled.Equals(false))  
  41.         {  
  42.             mapLocation.LandmarksEnabled = true;  
  43.             landmarksEnabled = true;  
  44.         }  
  45.   
  46.         else  
  47.         {  
  48.             mapLocation.LandmarksEnabled = false;  
  49.             landmarksEnabled = false;  
  50.         }  
  51.     }  
  52.   
  53.     private void btnPedestrianFeaturesEnabld_Tap(object sender, System.Windows.Input.GestureEventArgs e)  
  54.     {  
  55.         if(pedestrianFeaturesEnabled.Equals(false))  
  56.         {  
  57.             mapLocation.PedestrianFeaturesEnabled = true;  
  58.             pedestrianFeaturesEnabled = true;  
  59.         }  
  60.   
  61.         else  
  62.         {  
  63.             mapLocation.PedestrianFeaturesEnabled = false;  
  64.             pedestrianFeaturesEnabled = false;  
  65.         }  
  66.     }  
  67. }  
Here you see a video after changing all the properties, we will see in order according to the code shown above:

Map after tap on the button Heading
Image 1.8 Map after tap on the button Heading.

In this screen, we see that the map of the centre is turned to the left, if we had instead decreased the value of the property Heading, we had a rotation to the right of the centre of the map.

Map after tap on the button Pitch
Image 1.9 Map after tap on the button Pitch.

Map after tap on the button color mode
Image 1.10 Map after tap on the button color mode

In this image, after performing a tap on the button color mode, you have activated the Dark, suitable in low light conditions. I remember that the possible values are dark and light.

Map after tap on the button Landmarsk mode
Image 1.11 Map after tap on the button Landmarsk mode.

This makes three-dimensional visualization with the Egyptian Museum and Piazza Carlo Alberto, famous places that are located in Turin, this view is possible if we set the property to True LandmarskMode.

Map after the tap on the button Pedestrian features enabled
Image 1.12 Map after the tap on the button Pedestrian features enabled.

When the property PedestrianFeaturesEnabled is set to true, that is one way for the use of the map for a pedestrian.

Manage multiple levels

Suppose we want to show on our map points of interest, such as cinemas, fuel stations or restaurants. With this function, all this is possible; we need to resort to the class MapLayer, which contains a collection of objects of type MapOverlay, representing the points of interest that we want to show. Once the collection of objects, we can superimpose the new layer to the map, showing in this way the results obtained after the research phase. Consider this code example.
  1. public static void FindPosition(string position, Map maps)  
  2. {  
  3.     var locator = new Geolocator();  
  4.     var geocodequery = new GeocodeQuery();  
  5.     var map = maps;  
  6.   
  7.     if (!locator.LocationStatus.Equals(PositionStatus.Disabled))  
  8.     {  
  9.         try  
  10.         {  
  11.             geocodequery.GeoCoordinate = new GeoCoordinate(0, 0);  
  12.             geocodequery.SearchTerm = position;  
  13.             geocodequery.QueryAsync();  
  14.   
  15.             geocodequery.QueryCompleted += (sender, args) =>  
  16.             {  
  17.                 if (!args.Result.Equals(null))  
  18.                 {  
  19.                     var result = args.Result.FirstOrDefault();  
  20.                     map.Center = new GeoCoordinate(result.GeoCoordinate.Latitude, result.GeoCoordinate.Longitude);  
  21.                     map.ZoomLevel = 19;  
  22.   
  23.                     var point = new MapOverlay  
  24.                     {  
  25.                         GeoCoordinate = map.Center,  
  26.                         Content = new Ellipse  
  27.                         {  
  28.                             Fill = new SolidColorBrush(Colors.Black),  
  29.                             Height = 30,  
  30.                             Width = 30,  
  31.                         }  
  32.                     };  
  33.   
  34.                     var myposition = new MapOverlay  
  35.                     {  
  36.                         GeoCoordinate = map.Center,  
  37.                         Content = new TextBlock  
  38.                         {  
  39.                             Text = string.Concat(result.Information.Address.City," ",result.Information.Address.Country),  
  40.                             Height = 160,  
  41.                             Foreground = new SolidColorBrush(Colors.Red),  
  42.                             TextWrapping = TextWrapping.Wrap,                                      
  43.                             Margin = new Thickness(50, 10, 10, 10),  
  44.                         }  
  45.                     };  
  46.   
  47.                     MapLayer layer = new MapLayer();  
  48.                     layer.Add(point);  
  49.                     layer.Add(myposition);  
  50.                     map.Layers.Add(layer);  
  51.                 }  
  52.             };  
  53.         }  
  54.   
  55.         catch(Exception ex)  
  56.         {  
  57.             MessageBox.Show(ex.Message, AppResources.ApplicationTitle, MessageBoxButton.OK);  
  58.         }  
  59.     }  
  60.   
  61.     else  
  62.     {  
  63.         MessageBox.Show("Service Geolocation not enabled!", AppResources.ApplicationTitle, MessageBoxButton.OK);  
  64.     }  
  65. }  
We define a method that takes two arguments, the first of type string that matches the name of the place to be searched; the second is an object of type Map, that is part of the namespace Microsoft.Phone.Maps.Controls that will pass the reference of the control MapLocation that we defined in the screen. Let's re-use the classes Geolocator and GeocodeQuery that we have already seen in previous articles, so we will not dwell on them again. The novelty lies in the two new classes MapOverlay and MapLayer. The first represents all objects belonging to the final layer then we're going to overlay the current map. We define a new object of type MapOverlay and we have the value of the property GeoCoordinate with the latitude and longitude that we get from the event QueryCompleted exposed by the class GeocodeQuery. We also have another class properties MapOverlay called Content, being of type Object, we can define any object. We insert a control Ellipse, that will serve to show the point of interest that you have chosen; you should consider this part of the code.
  1. var point = new MapOverlay  
  2. {  
  3.    GeoCoordinate = map.Center,  
  4.    Content = new Ellipse  
  5.    {  
  6.       Fill = new SolidColorBrush(Colors.Black),  
  7.       Height = 30,  
  8.       Width = 30,  
  9.    },   
  10. };  
We will also show a second object MapOverlay containing the name of the Town and Country; we'll find the Address property, at the time of the query.
  1. var myposition = new MapOverlay  
  2. {  
  3.    GeoCoordinate = map.Center,  
  4.    Content = new TextBlock  
  5.    {  
  6.       Text = string.Concat(result.Information.Address.City," ",result.Information.Address.Country),  
  7.       Height = 160,  
  8.       Foreground = new SolidColorBrush(Colors.Red),  
  9.       TextWrapping = TextWrapping.Wrap,   
  10.       Margin = new Thickness(50, 10, 10, 10),  
  11.    }  
  12. };  
After this activity, we need to define a new object MapLayer. This class contains within it a collection of type MapOverlay, where using the Add() method, add one or more objects. The iteration remains exactly as a normal list, with the difference that will, typed. We cannot define or add a different object.
  1. MapLayer layer = new MapLayer();  
  2. layer.Add(point);  
  3. layer.Add(myposition);  
  4. map.Layers.Add(layer);  
We access the Map Layers class. Within the event, tap the button btnFindCoordinate and insert the method invocation FindPosition, passing as parameters the name of the place made up of a string variable, plus the reference to the control map called MapLocation.
  1. namespace GeoPositionSample  
  2. {  
  3.    public partial class MapLayers   
  4.    {  
  5.       public MapLayers()  
  6.       {  
  7.          InitializeComponent();  
  8.       }  
  9.   
  10.       private void btnFindCoordinate_Tap(object sender, System.Windows.Input.GestureEventArgs e)  
  11.       {  
  12.          MyPosition.FindPosition(tbxCity.Text,mapLocation);  
  13.       }  
  14.    }  
  15. }  
Before proceeding with application debugging, it is necessary to enable the capability ID_CAP_LOCATION and ID_CAP_LOCATION, otherwise the application will not work. In exploring solutions, we expand the directory Properties and click on the file WMAppManifest.xml as shown.

The Solution Explorer section in Visual Studio
Image 1.13 The Solution Explorer section in Visual Studio.

The Features section that we find in the file WMAppManifest
Image 1.14 The Features section that we find in the file WMAppManifest.

After we added the necessary items for the creation of our layer and the capability necessary, we need to update the map, this is possible by enhancing the method exposed by the control NokiaMaps Layers. This is always a collection that accepts an objects of type MapLayer. Also in this activity, we see the result that we will have on the map. We start the application, on the Home screen do a tap on Button Layers, arrived at the screen, we type the name of a place, as Caselle Torinese. If the search is successful, here is how the map looks after the search.

The map with the new layer, after searching for a location
Image 1.15 The map with the new layer, after searching for a location.

Conclusion

In this article on Geolocation, we started to see some of the features of Nokia Maps control. We started looking at how to leverage the Zoom property that allows you to zoom in or out the contents of the map and we saw all the possibilities for viewing, starting from Aerial to Terrain. Then was the ways to work on other properties to further customize the map, by the way Heading that allows the rotation of the map of the center. Then was the property PedestrianFeaturesEnabled, that adapts the content for use when we walk and finish, explaining how to manage one or more levels. In other words, to define a custom layer, we can overlay the current map to show information such as locations, points of interest and more. In the next article, we will see what placeholders are, how to define and create them and then superimpose the control NokiaMaps.

See also

Another 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


Similar Articles