Introduction.

We continue our path with geolocation services.

Before we begin, let's remind ourselves of what we saw in the previous article on the Nokia Maps control.

We analyzed the main functions, starting from the property ZoomLevel, able to change proportionally viewing the content on the map, then the alternative display types  from the default Aerial Terrain. We also covered other properties - allowing customization of the map, starting from the way Heading, with which you can rotate the map of the center, ending with PedestrianFeaturesEnabled for when we walk. Finally there was a brief introduction on levels -  the ability to create and superimpose custom layers on the map.  This allows us to to display one or more points of interest using MapOverlay class.

In this article, we will see how to insert one or more placeholders on the map, specically covering:

[TOC]

Remember to use geolocation services and maps,  you must enable the capability ID_CAP_LOCATION and ID_CAP_MAP, discussed in previous articles. Be found in the file WMAppManifest.xml the Features section.


Placeholder generic

As seen in the previous article, it is possible, by means of a layer, customize the map view so points of interest or our present position, all thanks to geolocation services. However, there are other ways to do this, we speak of the placeholder. There are two types: generic ones that will handle it in short and those called UserLocationMarker. It 'good to know that the SDK for Windows Phone 8 does not have these controls, but you need to add to our project the reference to Phone Toolkit for Windows Phone. The Phone Toolkit provides us developers a series of controls, including an element called pushpin. This control is what we're going to use to view your location on the map Control. Nokia Maps offers different 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.


Installing the Phone Toolkit

If available, we take over the project previously created with Visual Studio 2013, for those who have not had the opportunity to read the previous article, I leave the link to download the sample source code. We start Visual Studio 2013, the "File" menu select "Open" and immediately after "Project / Solution." For those who have downloaded the project from the above link, you go to select the file, depending on where you place it all after you extract the contents of the zip file. Once you open the project, "explores solutions" we place the cursor on the "References", right click and choose the command "Manage Nuget packages". We will use Nuget to install and add in the references of our project the Windows Phone Toolkit. In the dialog that follows, we write Windows Phone Toolkit.

Image 1.1 The Phone Toolkit on Nuget.

After finding the library, and clicked on the "Install" button, if all goes well, he, as shown in the figure, a green circle with a check mark in it, this is meaning that has been installed properly. We installed all you need; we look at what was added after installation of the Phone Toolkit:

Image 1.2 The Phone Toolkit in the references after installation.

We note that we have a new reference our project: Microsoft.Phone.Controls.Toolkit. Let us examine the placeholders as anticipated previously available.

 


Using the generic placeholder

Let's go back to our project, we place the cursor on "GeoPositionSample", right click, choose the command "Add", after "New Item", and choose the template "page vertical Windows Phone", as shown in the figure, and call it PushPinSample.

Image 1.3 The Add new item screen.

We insert the following code, in order to define the graphical interface. Before namespaces.

xmlns:Controls="clr-namespace:Microsoft.Phone.Maps.Controls;assembly=Microsoft.Phone.Maps"    

It should be inserted immediately after

x:Class="GeoPositionSample.PushPinSample"

This will use the control NokiaMaps within the screen; otherwise we will get an error if we tried to compile the project, or not to print the local GUI properly. After defining the namespace, insert the following code.

<!--LayoutRoot ? la griglia radice in cui viene inserito tutto il contenuto della pagina-->
  <Grid x:Name="LayoutRoot" Background="Transparent">
      <Grid.RowDefinitions>
          <RowDefinition Height="Auto"/>
          <RowDefinition Height="*"/>
      </Grid.RowDefinitions>
 
      <!--TitlePanel contiene il nome dell'applicazione e il titolo della pagina-->
      <StackPanel Grid.Row="0" Margin="12,17,0,28">
          <TextBlock Text="GeoPositionSample" Style="{StaticResource PhoneTextNormalStyle}"/>
          <TextBlock Text="PushPin sample" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
      </StackPanel>
 
      <!--ContentPanel - inserire ulteriore contenuto qui-->
      <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
          <Grid.RowDefinitions>
              <RowDefinition Height="*"/>
              <RowDefinition Height="Auto"/>
          </Grid.RowDefinitions>
 
              <StackPanel>
              <Controls:Map x:Name="mapLocation" Height="442" Width="480">
                  <toolkit:MapExtensions.Children>
                      <toolkit:Pushpin x:Name="myPushPin" Content="your position" Visibility="Collapsed"/>
                  </toolkit:MapExtensions.Children>
              </Controls:Map>
          </StackPanel>
 
          <Button Grid.Row="1" x:Name="btnFindCoordinate" Content="Find data" Tap="btnFindCoordinate_Tap"/>
      </Grid>
  </Grid>

If everything has been entered correctly, the screen will take on this aspect.

Image 1.4 The screen layout PushPinSample.

Defined graphical interface, we can handle everything you need for the inclusion of the generic placeholder. The first thing to do is to add the required namespace in file.xaml class pushpin.

xmlns:toolkit="clr-namespace:Microsoft.Phone.Maps.Toolkit;assembly=Microsoft.Phone.Controls.Toolkit"

This is because the class PushPin is part of the namespace Microsoft.Phone.Maps.Toolkit. Later, in xaml file of the screen, you need to add a property that we find in the toolkit, called MapExtensions. This is a holding area where all objects are grouped PhoneToolkit concerning controls Maps. We modify the code for controlling Maps as follows.

<Controls:Map x:Name="mapLocation" Height="442" Width="480">
                        <toolkit:MapExtensions.Children>
                            <toolkit:Pushpin x:Name="myPushPin"/>
                        </toolkit:MapExtensions.Children>
                    </Controls:Map>

Performed the change on the graphics, we should management code behind. What we need to do is enhance the property GeoCoordinate with the latitude and longitude that now we know if we followed all items up to now. Let's go back to our project, we open the file named MyPosition.cs and insert the following code.

public static async void MyPushPinPosition(Map maps)
        {
            var latitude = 0d;
            var longitude = 0d;
 
            try
            {
                var locator = new Geolocator();
                if (!locator.LocationStatus.Equals(PositionStatus.Disabled))
                {
                    var position = await locator.GetGeopositionAsync();
                    latitude = position.Coordinate.Latitude;
                    longitude = position.Coordinate.Longitude;
                    var pushpin = (Pushpin)  maps.FindName("myPushPin");
                    pushpin.GeoCoordinate = new GeoCoordinate(latitude, longitude);
                    pushpin.Visibility = System.Windows.Visibility.Visible;
                    maps.ZoomLevel = 19;
                    maps.Center = new GeoCoordinate(latitude, longitude);
                }
 
                else
                {
                    MessageBox.Show("Service Geolocation not enabled!", AppResources.ApplicationTitle, MessageBoxButton.OK);
                }
            }
 
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

What we are going to perform, is nothing more than create a static method by prefixing the async keyword to the method signature, because this GetPositionAsync () is a method of asynchronous. Let's see if geolocation services are active, because the user can at any time turn them off. We check everything using this line of code:

if (!locator.LocationStatus.Equals(PositionStatus.Disabled))

Checking the value of the enumerator PositionStatus, if different from Disabled runs all the code inside the if block, otherwise notify the user that geolocation services are disabled. This is also necessary to avoid an exception at runtime, if you try to run the search with location services disabled. Then we call the method GetPositionAsync (), belonging to the class Geolocator, which returns by the property Coordinate the latitude and longitude. Even this procedure should be already familiar because it's already been dealt with in the previous article. The news comes with these lines of code:

var pushpin = (Pushpin)  maps.FindName("myPushPin");
pushpin.GeoCoordinate = new GeoCoordinate(latitude, longitude);
pushpin.Visibility = System.Windows.Visibility.Visible;

The first is necessary to refer to the control Pushpin (generic placeholder), because being inside MapExtensions (in file.xaml), we cannot refer to it directly, but only by the method FindName () belonging to the control Maps. The second line of code does nothing but enhance the properties of the class GeoCoordinate pushpin with the latitude and longitude, to the location on the map. The last line of code simply makes visible the marker on the map, all setting the Visibility property with the value of the enumerator Visible Visibility. After this activity, is needed one more thing on the graphic: MainPage.xaml opens the file, and adds this line of code just below the button btnLayers xaml code found inside the StackPanel control.

<Button x:Name="btnPushPinSample" Content="PushPinSample" Tap="btnPushPinSample_Tap"/>

The new screen of MainPage should have this aspect.

Image 1.5 The screen layout MainPage.

The last thing to do is to manage the navigation from MainPage to PushPinSample, we execute it using the Navigate method () of the property NavigationService belonging to the namespace System.Windows.Navigation. Open the file MainPage.xaml.cs and insert the following code.

private void btnPushPinSample_Tap(object sender, System.Windows.Input.GestureEventArgs e)
        {
            NavigationService.Navigate(new Uri("/PushPinSample.xaml", UriKind.Relative));
        }


Test the generic placeholder

To tap on the button btnPushPinSample through the Navigate method (), we access the page PushPinSample. The method takes two arguments: the first, of type Uri where we will have to specify which page you want to access, in our case PushPinSample.xaml, the second is the type of navigation. We set the value Relative enumerator UriKind (all navigation between pages must be either Relative). After this activity, we are ready to run the application. F5 key, perform debugging and if there are no mistakes, this is the new home screen.

Image 1.6 The new home screen.

We note that we have the new button PushPinSample. We do a tap on it, and we will be led into the new screen that we designed before.

Image 1.7 The screen image PushPinSample.

We have a Map control and a Button called Maps Find position. Now let's do a tap on the button, and if everything is done correctly, this is the result of research position.

Image 1.8 The screen image PushPinSample after location research performed.

 

Inserting more placeholder

In this short procedure, it is seen as creating a placeholder, detect using geolocation services the user's location, the property value of the control GeoCoordinate pushpin, and then show it on the map. However, there are cases where you need to specify multiple points of interest, as if we execute the download from a service on which we have more latitude and longitude coordinates to manage. The most suitable solution in this case, is to create the controls pushpin directly from code. Suppose you want to display a number of hotels in a specific area. We will create first class, where we will gather all the necessary information. Let's go back to the project, we place the cursor on the project name in the Solution Explorer, right-click, and select the command "Add" and immediately after "Class". We assign the name "Hotel" to the newly created class, after we replace the code with this.

using System.Device.Location;
 
namespace GeoPositionSample
{
    class Hotel
    {
        public GeoCoordinate Coordinate { get; set; }
        public string NameHotel { get; set; }
    }
}

It was created a class called Hotel, defined a property of type GeoCoordinate, which we will use later to assign values of latitude and longitude, another property of type string, which we will use to show the name of the hotel on the map. With the same procedure that we used for the creation of the class hotel, instead we create a new page using the "New Item", using the template "page vertical Windows Phone", and we call it "MultiplePushpin" as shown in the figure.

Image 1.9 The Add new item screen.

Remaining in the xaml file, insert the following code to define the graphics, starting with the namespace needed, to use the map and controls Phone Toolkit.

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 rest to define the graphics.

<!--LayoutRoot ? la griglia radice in cui viene inserito tutto il contenuto della pagina-->
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
 
        <!--TitlePanel contiene il nome dell'applicazione e il titolo della pagina-->
        <StackPanel Grid.Row="0" Margin="12,17,0,28">
            <TextBlock Text="GeoPositionSample" Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock Text="MultiplePushPin" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>
 
        <!--ContentPanel - inserire ulteriore contenuto qui-->
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
 
                <StackPanel>
                <Controls:Map x:Name="mapLocation" Height="442" Width="480">
                    <toolkit:MapExtensions.Children>
                        <toolkit:MapItemsControl>
                            <toolkit:MapItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <toolkit:Pushpin
                                        x:Name="myPushPin"
                                        Content="{Binding NameHotel}"
                                        GeoCoordinate="{Binding Coordinate}"/>                                      
                                </DataTemplate>
                            </toolkit:MapItemsControl.ItemTemplate>
                        </toolkit:MapItemsControl>
                    </toolkit:MapExtensions.Children>
                </Controls:Map>
            </StackPanel>
 
            <Button Grid.Row="1" x:Name="btnFindCoordinate" Content="Find Hotel" Tap="btnFindCoordinate_Tap"/>
        </Grid>
    </Grid>

If we remember the code of the screen PushPinSample, we will notice some changes as regards the map, in other words it is defined a new object, MapItemsControl:

<toolkit:MapItemsControl>
               <toolkit:MapItemsControl.ItemTemplate>
                   <DataTemplate>
                       <toolkit:Pushpin
                           x:Name="myPushPin"
                           Content="{Binding NameHotel}"
                           GeoCoordinate="{Binding Coordinate}"/>                                      
                   </DataTemplate>
               </toolkit:MapItemsControl.ItemTemplate>
           </toolkit:MapItemsControl>

It is nothing more than a control that allows us to create a template, define the structure, and eventually overlap with the map layers were calling just as with the class MapOverlay. In our case, we have defined a DataTemplate inside, control pushpin, also note that compared first, the Content property and GeoCoordinate are binding with the properties that we have defined in the class Hotel. We shall not stop to explain what is binding, as beyond the scope of the article. Also finished this activity, our screen should take this aspect.

Image 1.10 The new screen MultiplePushPin.

After the part about the graphics, with the F7 key pass code editor. We will have to first add the namespace necessary to use all the functionality required.

using Microsoft.Phone.Maps.Toolkit;
using System.Collections.ObjectModel;
using System.Device.Location;

The first namespace, you need to make use of the controls belonging to Phone toolkit, the second will be used at the time that we will create a collection of type ObservableCollection to define all the data of hotels, while the last is necessary to make use of the services geolocation. We replace the code in the class with the following MultiplePushPin.

using System.Linq;
using System.Windows;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Maps.Toolkit;
using System.Collections.ObjectModel;
using System.Device.Location;
 
namespace GeoPositionSample
{
    public partial class MultiplePushPin : PhoneApplicationPage
    {
        ObservableCollection<Hotel> Hotels = new ObservableCollection<Hotel>();
 
        public MultiplePushPin()
        {
            InitializeComponent();
        }
 
        private void btnFindCoordinate_Tap(object sender, System.Windows.Input.GestureEventArgs e)
        {
              Hotels.Add(  new Hotel { Coordinate = new GeoCoordinate(45.07146, 7.68349), NameHotel = "Town House 70" });
              Hotels.Add(  new Hotel { Coordinate = new GeoCoordinate(45.07257, 7.68411), NameHotel = "Hotel Chelsea" });
              Hotels.Add(  new Hotel { Coordinate = new GeoCoordinate(45.07107, 7.68062), NameHotel = "Hotel Azalea" });
              Hotels.Add(  new Hotel { Coordinate = new GeoCoordinate(45.06777, 7.68317), NameHotel = "Hotel San Carlo"});
              Hotels.Add(  new Hotel { Coordinate = new GeoCoordinate(45.06714, 7.68516), NameHotel = "Hotel MioMay" });
 
              ObservableCollection<DependencyObject> hotels = MapExtensions.GetChildren(mapLocation);
              var result = hotels.FirstOrDefault(w => w.GetType().Equals(typeof(MapItemsControl))) as MapItemsControl;
 
              var midLatitude = Hotels.Average(a => a.Coordinate.Latitude);
              var midLongitude = Hotels.Average(b => b.Coordinate.Longitude);
 
              result.ItemsSource = Hotels;
              mapLocation.ZoomLevel = 16;
              mapLocation.Center = new GeoCoordinate(midLatitude, midLongitude);
        }
    }
}

Was defined an ObservableCollection type Hotel, defining the coordinates of latitude and longitude, plus the name of the hotel with two properties exposed by the class Hotel. A clarification: it is not about dummy data but real, Hotel in the city of Turin. Inside the event tap the button btnFindCoordinate, is enhanced with the actual data collection Hotels. This is definitely the most interesting part:

ObservableCollection<DependencyObject> hotels = MapExtensions.GetChildren(mapLocation);
var result = hotels.FirstOrDefault(w => w.GetType().Equals(typeof(MapItemsControl))) as MapItemsControl;
var midLatitude = Hotels.Average(a => a.Coordinate.Latitude);
var midLongitude = Hotels.Average(b => b.Coordinate.Longitude);
result.ItemsSource = Hotels;
mapLocation.ZoomLevel = 16;
mapLocation.Center = new GeoCoordinate(midLatitude, midLongitude);

Leveraging MapExtensions class, we go to retrieve all child elements within it by the method GetChildren (), then with the extension method FirstOrDefault recover the element MapItemsControl, valuing the ItemsSource property with the values of the ObservableCollection Hotels. Always with the extension method, in this case Average, perform average latitude and longitude and to exploit then the property of the Center Control Maps.

mapLocation.Center = new GeoCoordinate(midLatitude, midLongitude);

Finally, we set the property value sixteen ZoomLevel always control Maps, to enlarge the display of points of interest. Last thing to do is add in MainPage the Button control for navigation screen MultiplePushPin. Open the file MainPage.xaml, and insert the following code inside the StackPanel control, where there is already code of the other buttons.

<Button x:Name="btnMultiplePushPin" Content="Multiple push pin" Tap="btnMultiplePushPin_Tap"/>

F7 key, we enter in the code editor and manage the event Tap.

private void btnMultiplePushPin_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
    NavigationService.Navigate(new Uri("/MultiplePushPin.xaml", UriKind.Relative));
}

This will be the new interface of the MainPage after the addition of the new button.

Image 1.11 new screens MainPage.

We can now test the application, F5 and start the debugging, we do a tap on the button Multiple push pin, entered the new screen, another tap on the button Find Hotel, if all goes well, this is how will the map at the end of the search.

Image 1.12 map to search performed.


Using the placeholder UserLocationMarker

In some cases, control pushpin is not ideal to report the location of the user, especially when moving. The Phone toolkit provides another placeholder, called UserLocationMarker. The management of this placeholder is almost identical to the generic one. As we will see the changes to be made are really minimal. Let's go back to the project and open the file PushPinSample.xaml, and modify the existing code

    <StackPanel>
    <Controls:Map x:Name="mapLocation" Height="442" Width="480">
        <toolkit:MapExtensions.Children>
            <toolkit:Pushpin x:Name="myPushPin" Content="your position" Visibility="Collapsed"/>
        </toolkit:MapExtensions.Children>
    </Controls:Map>
</StackPanel>

With this following

<StackPanel>
    <Controls:Map x:Name="mapLocation" Height="442" Width="480">
        <toolkit:MapExtensions.Children>
            <toolkit:UserLocationMarker x:Name="myUserLocationMarker" Visibility="Collapsed"/>
        </toolkit:MapExtensions.Children>
    </Controls:Map>
</StackPanel>

The only difference lies in the fact that we have changed the control, in other words from Pushpin to UserLocationMarker, and removed the Content property, for the rest is the same as before. Open the file MyPosition and we're going to replace this piece of code in the method MyPushPinPositon ():

var pushpin = (Pushpin)maps.FindName("myPushPin");
pushpin.GeoCoordinate = new GeoCoordinate(latitude, longitude);
pushpin.Visibility = System.Windows.Visibility.Visible;

With this.

var userLocationMarker = (UserLocationMarker)maps.FindName("myUserLocationMarker");
      userLocationMarker.GeoCoordinate = new GeoCoordinate(latitude, longitude);
      userLocationMarker.Visibility = Visibility.Visible;

Even in this circumstance, the changes are really minimal, we change the variable name pushpin with userLocationMarker, and we recover by the method FindName the control name or myUserLocationMarker, while the properties GeoCoordinate Visibility and remain identical to those of the control pushpin.


Test control UserLocationMarker

Perform these changes, we can again start debugging the application by pressing F5, MainPage screen, tap on the button PushPinSample, and then tap on the Find button position. If everything was done correctly, this is how you will present the map with the new control.

Image 1.13 The map control UserLocationMarker.


Conclusion.

In this article, it was explained what are placeholders, how to define, create and then superimpose the control NokiaMaps, but starting from the installation of Phone Toolkit, need to be able to make use. Later, with the control pushpin, was defined as display the user's location, and for the signaling of multiple points of interest. Finally, we made a brief overview of what is control UserLocationMarker, also part of Phone Toolkit. In the next article, we will see how you can view a route on the map and how to calculate a route.


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.