sábado, 3 de marzo de 2012

Mostrando la ubicación actual en un Mapa de Bing en Windows Phone

Después de haber configurado nuestra aplicación para poder usar Mapas de Bing y de tener en cuenta algunas consideraciones para el uso de los servicios de localización de nuestro dispositivo, vamos a aprender a marcar ubicaciones o locaciones en nuestros mapas usando Pushpins o marcadores.

El ejercicio consistirá en marcar nuestra ubicación con un color y un conjunto de coordenadas de sitios conocidos a nuestro alrededor.

Primero empezaremos entonces por declarar a nivel de nuestra página la clase GeoCoodinateWatcher a la instancia le daremos el nombre de watcher, luego de eso en el constructor creamos un nuevo objeto y nos suscribimos a los eventos PositionChanged y StatusChanged, esto debería generar el siguiente código:

 using System;  
 using System.Collections.Generic;  
 using System.Linq;  
 using System.Net;  
 using System.Windows;  
 using System.Windows.Controls;  
 using System.Windows.Documents;  
 using System.Windows.Input;  
 using System.Windows.Media;  
 using System.Windows.Media.Animation;  
 using System.Windows.Shapes;  
 using System.Device.Location;  
 using Microsoft.Phone.Controls;  
   
 namespace BingMaps.Demo  
 {  
   public partial class MainPage : PhoneApplicationPage  
   {  
     GeoCoordinateWatcher watcher;  
   
     // Constructor  
     public MainPage()  
     {  
       InitializeComponent();  
       watcher = new GeoCoordinateWatcher ();  
       watcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(watcher_PositionChanged);  
       watcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(watcher_StatusChanged);  
     }  
   
     void watcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)  
     {  
       throw new NotImplementedException();  
     }  
   
     void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)  
     {  
       throw new NotImplementedException();  
     }  
   }  
 }  

Recuerda agregar el nivel de sensibilidad al que se someterá el servicio de localización, ya que esto determina cada cuanto se dispara el evento PositionChanged, para eso usamos la propiedad MovementThreshold, además no debemos olvidar invocar el método Start para iniciar el servicio de localización. El código del constructor quedaría así:

     // Constructor  
     public MainPage()  
     {  
       InitializeComponent();  
       watcher = new GeoCoordinateWatcher ();  
       watcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(watcher_PositionChanged);  
       watcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(watcher_StatusChanged);  
   
       watcher.MovementThreshold = 20;
       watcher.Start();  
     }  

En este momento las dos suscripciones a los eventos no tienen implementación, están lanzando por defecto una excepción, limpiamos los dos métodos y vamos a implementar como obtener nuestra posición actual implementando el método asociado al evento PositionChanged. Para hacer que nuestra posición actual varie, vamos a declarar un marcador o pushpin a nivel de la clase justo al lado del watcher, asi;

     GeoCoordinateWatcher watcher;  
     Pushpin actualPosition;  

Y en el método asociado al evento PositionChanged vamos a controlar que este marcador no haya sido instanciado antes para removerlo del mapa y volverlo a instanciar para cambiarlo de posición. Aquí tengamos en cuenta si hemos dejado nuestro mapa tal cual como quedó al tomarlo del cuadro de herramientas, su nombre por defecto es map1, de otro buscamos cual es su nombre. El código de este método quedaría así:

     void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)  
     {  
       if (actualPosition != null)  
         map1.Children.Remove(actualPosition);  
   
       actualPosition = new Pushpin();  
       actualPosition.Location = e.Position.Location;  
       actualPosition.Content = "Me"; //Esta será la etiqueta del marcador
       map1.Children.Add(actualPosition);  
   
       map1.SetView(actualPosition.Location, 10); //El 10 es el zoom del mapa 
     }  

Si probamos en este momento veremos como la posición que simulemos en el emulador se muestra en el mapa


Para implementar el método StatusChanged vamos a crear en la pantalla 3 nuevos controles solo para efectos de este demo, yo sugeriría que se añadiera un botón de iniciar y uno de detener al Application Bar pero para aprender más del Application Bar, haré un post más adelante.


En MSDN hay un  código de referencia para implementar StatusChanged para efectos de este post lo tomaré tal cual, por lo que si lo están siguiendo recuerda recuerda nombrar los nuevos controles como los llaman en el código: statusTextBlock, startLocationButton y stopLocationButton.

     void watcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)  
     {  
       switch (e.Status)  
       {  
         case GeoPositionStatus.Disabled:  
           // The Location Service is disabled or unsupported.  
           // Check to see whether the user has disabled the Location Service.  
           if (watcher.Permission == GeoPositionPermission.Denied)  
           {  
             // The user has disabled the Location Service on their device.  
             statusTextBlock.Text = "you have this application access to location.";  
           }  
           else  
           {  
             statusTextBlock.Text = "location is not functioning on this device";  
           }  
           break;  
   
         case GeoPositionStatus.Initializing:  
           // The Location Service is initializing.  
           // Disable the Start Location button.  
           startLocationButton.IsEnabled = false;  
           break;  
   
         case GeoPositionStatus.NoData:  
           // The Location Service is working, but it cannot get location data.  
           // Alert the user and enable the Stop Location button.  
           statusTextBlock.Text = "location data is not available.";  
           stopLocationButton.IsEnabled = true;  
           break;  
   
         case GeoPositionStatus.Ready:  
           // The Location Service is working and is receiving location data.  
           // Show the current position and enable the Stop Location button.  
           statusTextBlock.Text = "location data is available.";  
           stopLocationButton.IsEnabled = true;  
           break;  
       }  
     }  

Recuerda además implementar el código de los dos nuevos botones

     private void startLocationButton_Click(object sender, RoutedEventArgs e)  
     {  
       startLocationButton.IsEnabled = false;  
       stopLocationButton.IsEnabled = true;  
       watcher.Start();  
     }  
     private void stopLocationButton_Click(object sender, RoutedEventArgs e)  
     {  
       startLocationButton.IsEnabled = true;  
       stopLocationButton.IsEnabled = false;  
       watcher.Stop();  
     }  

Y probar tu aplicación :D


Vamos a implementar además el poder cambiar el tipo de mapa que vemos, para esto vamos a habilitar el botón vista que tenemos en el Application Bar



Y en el código asociado podemos establecer el tipo de vista, por vista aérea o vista de calles.

En la vista aérea el mapa se vería así


No olviden que para los mapas de Bing también pueden usar Mapas Estáticos. Espero les haya sido útil

Sorey
Publicar un comentario en la entrada