Hace algunas semanas creé el primer mapa de México en XAML.  Esta iniciativa animó a unos buenos amigos a perfeccionar esta primer aproximación del mapa de México en XAML para poder utilizarlo en nuestras aplicaciones Silverlight / WPF.  En este artículo veremos cómo crear un control de usuario reutilizable a partir de este XAML para poder usarlo en la plataforma Silverlight.

Para iniciar, es buena idea mostrar el mapa de XAML que usaremos.  El mapa de México en XAML lo pueden descargar del sitio de contenido de La Liga Silverlight.  Para mostrar el mapa estoy usando KaXaml, una excelente herramienta para edición de XAML alternativa a las ya conocidas herramientas como Visual Studio .NET 2008 o Expression Blend.

Muy bien, para iniciar debemos hacer notar los siguiente:

  • Cada estado de la república es un Path, el cual está envuelto en un contenedor <Canvas> con el nombre de cada estado en la propiedad x:Name, esto para poder tener control sobre cada uno de los estados (al darle click sobre cada uno de ellos o al mover el mouse encima de él). 32 estados = 32 Path = 32 Canvas.
  • El <Canvas> raíz de todo el mapa se llama MapaMexico.  Este <Canvas> es el contenedor de los 32 estados del país

Comenzando

Crearemos una aplicación de tipo Silverlight por medio de Visual Studio .NET 2008 y usando las plantillas.  A esta aplicación le llamaremos PortalMexico como a continuación se muestra en la ilustración:

Posteriormente seleccionamos la opción de crear una aplicación Web y cerramos la ventana de diálogo.  Una vez descargado el mapa de México en XAML, agregamos los dos archivos Mexico.xaml y Mexico.xaml.cs al proyecto de Silverlight.  Estos archivos son el diseño en XAML y el code-behind relacionado a ese XAML respectivamente.

El mapa de México en XAML ya incluye código preconstruído el cual colorea el estado de la república Mexicana que esté seleccionado a través del cursor del mouse.  Este código es bastante sencillo y se logra de la siguiente manera:

public Mexico()
     {
         InitializeComponent();
         fillBrush = (Brush)this.Resources["brochaVerde"];
         strokeBrush = (Brush)this.Resources["brochaNegra"];
 
         foreach (Canvas estado in MapaMexico.Children)
         {
             if (estado is Canvas)
             {
                 RegisterEvents(estado as Canvas);
             }
         }
 
     }

Vale la pena notar que el código itera sobre todos los estados (Canvas) que están en el Canvas raíz (MapaMexico) y por cada uno ejecuta el método RegisterEvents() que a continuación se muestra:

void RegisterEvents(Canvas estado)
        {
            estado.MouseEnter += new MouseEventHandler(estado_MouseEnter);
            estado.MouseLeave += new MouseEventHandler(estado_MouseLeave);
            estado.MouseLeftButtonUp += new MouseButtonEventHandler(estado_MouseLeftButtonUp);
        }

Como podrás notar, para los eventos MouseEnter (al entrar el cursor del mouse sobre el Canvas), MouseLeave (al salir el cursor del mouse del Canvas) y MouseLeftButtonUp (al hacer clic completo con el mouse sobre un estado (Canvas)) se asignan los manejadores de evento:

estado_MouseEnter

estado_MouseLeave

estado_MouseLeftButtonUp

…respectivamente.  Esto quiere decir que, estos métodos (denominados manejadores de eventos por tratarse de métodos que se ejecutan cuando se dispara un evento) se comparten para los 32 estados!  librándonos de escribir más código del necesario, el cual también pudo haber sido resuelto de la siguiente manera pero menos eficiente:

RegisterEvents(NuevoLeon);
RegisterEvents(DistritoFederal);
RegisterEvents(Jalisco);
RegisterEvents(Sinaloa);
RegisterEvents(Sonora);
//etc...!

O peor aún:

NuevoLeon.MouseEnter += new MouseEventHandler(NuevoLeon_MouseEnter);
NuevoLeon.MouseLeave += new MouseEventHandler(NuevoLeon_MouseLeave);
NuevoLeon.MouseLeftButtonUp += new MouseButtonEventHandler(NuevoLeon_MouseLeftButtonUp);
Chiapas.MouseEnter +=new MouseEventHandler(Chiapas_MouseEnter);
//...y un largo etc.

Asimismo, cuando haces clic sobre un estado del mapa de México, te muestra el navegador un mensaje de alerta con el nombre del estado que has seleccionado.  De hecho lo que te muestra no es más que el nombre del Canvas que envuelve el Path que representa el estado, tal y como lo podemos apreciar en el siguiente fragmento de código tomado del code-behind del mapa:

void estado_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
 
            HtmlPage.Window.Alert(((Canvas)sender).Name);
        }

Es notable la presencia de la clase HtmlPage de Silverlight, la cual encapsula toda la funcionalidad necesaria del HTML Bridge de Silverlight.  Esta característica permite manipular el DOM del navegador con .NET dentro del plugin de Silverlight!!!  Esta es uno de los componentes que en lo personal considero bastante potente en esta plataforma y motivo suficiente para incluir Silverlight en todos nuestros proyectos Web ya que si abrimos un poco nuestra imaginación podremos darnos cuenta que tal vez, y digo, tal vez… no volvamos a necesitar crear scripts de Javascript para nuestras aplicaciones Web.  Este tema merece artículos en específico que próximamente estarán publicados en este blog y en La Liga Silverlight.

Vale la pena probar el mapa de México en XAML tal cual se puede descargar de La Liga Silverlight, sin modificaciones para poder entender lo que hemos explicado hasta el momento.  Para que la aplicación PortalMexico inicie con Mexico.xaml en vez de con Page.xaml, simplemente modifica la siguiente línea en el archivo App.xaml.cs, el cual es el archivo de código global para toda nuestra aplicación Silverlight, y posteriormente ejecuta la aplicación presionando la tecla F5 o eligiendo la opción Start Debugging del menú Debug en Visual Studio .NET 2008 (por favor toma en cuenta el nombre de espacio Mexico que contiene la clase Mexico)

private void Application_Startup(object sender, StartupEventArgs e)
{
    this.RootVisual = new Mexico.Mexico();
}

Muy bien, ya que explicamos la manera de cómo se están adjuntando los manejadores de eventos a los diferentes eventos para cada estado y qué sucede cuando un usuario hace clic en algún estado es momento de implementar nuestro control de usuario en la aplicación Silverlight:  Es hora de reutilizar Mexico.xaml en Page.xaml :)