API Google Maps II: ASP.NET

API Google Maps (II) ASP.NET

En este segundo artículo del tutorial, hablamos de insertar el API de Google Maps dentro de un Web Forms de ASP.NET, y trabajar con él desde código servidor a código de cliente.

El API de Google Maps, únicamente trabaja con JavaScript, por lo que en este post, lo que vamos a realizar es ubicar el control de mapa dentro del marcado HTML de un Web Form, y posteriormente mediante un control ListBox de ASP, enviar una serie de coordenadas geográficas (Latitud, Longitud) al API, el cual mostrará la ciudad seleccionada del listado.

Para ello, lo primero, ubicamos el API dentro del marcado en una capa, introduciendo nuestra clave en sustitución del texto TU_CLAVE_API, como se explica en el anterior post.

Una vez agregado el mapa, introducimos un panel Ajax, al que le vamos a introducir una serie de componentes, los cuales, en unos casos nos van a servir para interactuar con el usuario, y en otros para interactuar entre lenguaje servidor y lenguaje cliente.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="APIGoogleMaps.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>API Google Maps</title>

    <script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?key=TU_CLAVE_API&sensor=false"></script>
    <script type="text/javascript">
        function Init() {
            var nLat = 0.0;
            var nLon = 0.0;
            var zoom = <%=Zoom %>;
            if (navigator.geolocation) {
                navigator.geolocation.getCurrentPosition(function (position) {
                    nLat = position.coords.latitude;
                    nLon = position.coords.longitude;
                    document.getElementById("lat").value = nLat;
                    document.getElementById("lon").value = nLon;
                    MapIt(nLat, nLon, zoom);
                });
            }
        }

        function MapIt(lat, lon, zoom) {
            if (lat == null || lon == null || zoom  == null) {
                lat = document.getElementById("lat").value;
                lon = document.getElementById("lon").value;
                zoom = <%=Zoom %>;
            }

            var myOptions = {
                center: new google.maps.LatLng(lat, lon),
                zoom: zoom,
                mapTypeId: google.maps.MapTypeId.ROADMAP
            };
            var mapGoogle = new google.maps.Map(document.getElementById("myMap"), myOptions);
        }
    </script>

</head>
<body>
    <form id="form1" runat="server">
        <asp:XmlDataSource ID="XmlDS" runat="server" DataFile="~/Places.xml"></asp:XmlDataSource>
        <asp:ScriptManager ID="ScriptManager1" runat="server" />
        <div style="margin: auto; width: 800px; height: 600px">
            <asp:UpdatePanel runat="server" ID="Panel">
                <ContentTemplate>
                    <div style="float: right; width: 200px; height: 400px;">
                        <asp:ListBox runat="server" ID="LbCities" Width="100%"
                        Height="200px" DataSourceID="XmlDS" DataTextField="City" DataValueField="Id"
                        OnSelectedIndexChanged="LbCitiesSelectedIndexChanged" Rows="6" AutoPostBack="True" />
                        <asp:Button runat="server" ID="BtnGo" Text="Ir!"
                        OnClientClick="MapIt()" OnClick="BtnGoClick" />
                        <asp:Literal runat="server" ID="TextCity"/>
                        <input id="lat" runat="server" type="hidden" />
                        <input id="lon" runat="server" type="hidden" />
                    </div>
                </ContentTemplate>
            </asp:UpdatePanel>
            <div id="myMap" style="float: left; width: 600px; height: 600px;">
                <script>Init('myMap')</script>
            </div>
        </div>
    </form>
</body>
</html>

Para pasar variables entre servidor y cliente podemos introducir dentro del JS variables de servidor mediante este tag <%=VarServidor %>, esto es útil cuando se está haciendo el loading de la página, después, una vez cargada la página el contenido del JS no contendrá un acceso a la variable de servidor, sino el valor de la variable, por lo que solo podremos enviar valores de esta manera realizando postbacks. La otra opción sería a través de campos de formulario hidden, los cuales van a ser actualizados desde el servidor, y leídos desde el API, sin recargar la página.

El código que hemos cargado, contiene varias funciones JavaScript, «Init()» carga el API, y en el proceso intenta obtener la localización del usuario desde el navegador mediante la función de HTML5 «navigator.geolocation», de ésta forma la primera posición del mapa será la ubicación del cliente. La segunda función «MapIt(lat, lon, zoom)» establecerá la posición y el zoom o escala al que queremos mostrar los datos; La firma de la segunda función, conlleva el paso de variables de latitud, longitud y el factor de escala del zoom.

Nota: La solicitud de coordenadas por el navegador requiere que el usuario acepte que el navegador rastree la ubicación, de no aceptarlo el API no se centrará en nuestra ubicación.

Además de las funciones JavaScript, el WebForm contiene un objeto XMLDataSource de ASP.NET, el cual provee al ListBox, los datos de este XML que está a continuación, para permitirnos seleccionar una ciudad y situarnos.

<?xml version="1.0" encoding="utf-8" ?>
<Places>
  <Place Id="0" City="Madrid" Lat="40.4167754" Lon="-3.7037902"/>
  <Place Id="1" City="Berlin" Lat="52.519171" Lon="13.4060912"/>
  <Place Id="2" City="Roma" Lat="41.9015141" Lon="12.4607737"/>
  <Place Id="3" City="Paris" Lat="48.856614" Lon="2.3522219"/>
  <Place Id="4" City="Nueva York" Lat="40.7143528" Lon="-74.0059731"/>
</Places>

En el CodeBehind creamos una propiedad pública llamada Zoom, la cual es la variable que hemos enlazado en el JS. En el evento Load de la página seteamos esta propiedad. Por último configuramos los eventos SelectedIndexChanged y Click del ListBox y el Botón respectivamente.

El ListBox selecciona la ciudad a la que queremos acceder, y establece las coordenadas en los correspondientes hidden y el Botón desencadena la función JS «MapIt()» a la par que modifica un Literal dando la bienvenida a esa ciudad.

using System;
using System.Linq;
using System.Xml.Linq;

namespace APIGoogleMaps
{
    public partial class Default : System.Web.UI.Page
    {
        public int Zoom { get; set; }

        protected void Page_Load(object sender, EventArgs e)
        {
            Zoom = 14;
        }

        protected void LbCitiesSelectedIndexChanged(object sender, EventArgs e)
        {
            var xml = XDocument.Load(Request.MapPath("~/Places.xml"));
            var query = from q in xml.Descendants("Place")
                        select new
                        {
                            Id = q.Attribute("Id").Value,
                            City = q.Attribute("City").Value,
                            Lat = q.Attribute("Lat").Value,
                            Lon = q.Attribute("Lon").Value
                        };
            var place = query.Where(q => q.Id == LbCities.SelectedValue).ToList().FirstOrDefault();
            if (place != null)
            {
                this.lat.Value = place.Lat;
                this.lon.Value = place.Lon;
            }
        }

        protected void BtnGoClick(object sender, EventArgs e)
        {
            const String welcome = "Bienvenid@ a {0}";
            TextCity.Text = String.Format(welcome, LbCities.SelectedItem);
        }
    }
}

Finalmente obtendremos algo similar a esto:
Berlín

o este otro ejemplo, yendo a Nueva York
Berlín