Empezando con Windows Phone 7.1 (y IX) – Mi Panorama

Dándole vueltas a la organización de pantallas de la aplicación estoy pretendiendo que el usuario pueda disponer de información sobre sus sitios de interés de una manera sencilla y sin que tenga que estar realizando filtros manuales que puedan complicar la utilización de la misma. Así, por ejemplo, un usuario puede querer ver de forma automática, los sitios que son de su interés que se encuentren próximos a su ubicación, quizá los más visitados, o los marcados como favoritos…

Dentro de Windows Phone vais a poder encontrar fundamentalmente dos controles para la presentación de datos (bueno al menos dos, para lo que a esta entrada se refiere). Uno de ellos es el control “Pivot“. Este control es útil para presentar información o colecciones de datos divididos en subconjuntos.

Desde un punto de vista clásico de análisis de la información, las tablas dinámicas o pivot tables son  utilizadas para analizar fracciones o subconjuntos de datos agrupados según alguna característica común. Por ejemplo, una base de datos conteniendo gran información demográfica es difícil de analizar. Normalmente esta información suele segmentarse para facilitar su análisis según el sexo, edad, ingresos, estudios, ubicación geográfica, etc…

Siguiendo esa analogía, el control Pivot tiene una orientación más analítica de la información que quieres presentar en tu aplicación. Un buen ejemplo es el cliente de correo que te permite organizar la vista de tus mensajes de correo según quieras ver “Todos”, “Los mensajes Sin Leer”, “Urgentes”, etc…

Presentación de un Control Pivot

Presentación de un Control Pivot

Existe otro control de presentación, que por lo que estoy viendo es el que más se ajusta a mis necesidades que es el control “Panorama“. Este control es una de las incorporaciones de Presentación y Usabilidad más originales de la interfaz de Windows Phone. Al contrario que en otros casos, donde la vista o página está pensada para adaptarse al tamaño de la pantalla. Panorama es un marco ancho, muy ancho. Tanto que pueden caber varios anchos de pantalla para presentar el total de la información.

Presentación de un Control Panorama

Presentación de un Control Panorama

El objetivo es disponer en una sola pantalla de diferentes presentaciones de datos, así como de servicios que puedan resultar de utilidad para el usuario. Un par de ejemplos son la aplicación a través de la cual puedes ver Imágenes en tu Windows Phone, Zune o la aplicación oficial de Facebook (desde mi humilde punto de vista, todavía no muy lograda aunque rodando por buen camino).

Así pues, voy a decantarme por una vista principal con un control de tipo Panorama. Para ello hay que empezar con la organización de la información.

La anatomía de un control Panorama es la siguiente:

Anatomía Panorama

Anatomía del Control Panorama

El control Panorama está formado por tres capas diferentes:

  • Background: Un panel que permite mostrar y animar el contenido del fondo.
  • Title: Un panel utilizado para mostrar y animar el título.
  • Items: La capa que muestra los diferentes PanoramaItems que definamos en nuestro control y que se distribuyen horizontalmente.

Dice la documentación que, en el caso de que estés utilizando una imagen como fondo para tu control Panorama, y dejas la propiedad “Build Action” asociada a dicha imagen en modo “Content”, la carga del fichero se produce de manera asíncrona y puede llegar a apreciarse cierto retardo en la carga de la imagen. Es mejor dejar dicha propiedad como “Resource” de esta manera, la imagen se incluirá como un recurso más de la aplicación cargándose en el lanzamiento de la misma. Siendo sincero, yo no he percibido mucho cambio a simple vista (no he hecho ninguna prueba metódica de tiempos de carga). Simplemente tenedlo en cuenta.

Uno de los aspectos visuales más llamativos del control panorama es que, Fondo, Título y Contenido se mueven a distintas velocidades cuando deslizas la pantalla con el ratón (difícil de mostrar sólo con imágenes) dando así cierta sensación de profundidad muy lograda.

Vamos a algo concreto: Me gusta la fotografía pero mi habilidad como diseñador gráfico está fuera de toda discusión (todo el muno estará de acuerdo en que es desastrosa). Decidí montar dos fondos muy sencillos para mi Panorama. El primero es una sección de una fotografía que tomé a un tronco un día con los amigos en el campo y, la otra, es una variación de la misma, pero dejando un buen espacio en blanco para facilitar el contraste entre el fondo y las fuentes utilizadas para mostrar los contenidos. Tendré que hacer pruebas, pero la idea queda ahí.

Ejemplos de Fondo Panorama

Ejemplos de Fondo Panorama

En mi caso, como podéis ver un poco más arriba, he decidido utilizar como fondo una imagen. Esta imagen tiene unas dimensiones de 2048×800 píxeles. Los 800 px de alto son importantes para que no haya ningún redimensionamiento vertical de la imagen que pueda afectar a su aspecto.

Mientras no engañe a mi amigo Dannan (o no se deje engañar) para que me ayude con cosas muy básicas de retoque fotográfico, mis herramientas se reducirán al Paint (tengo instalado Gimp y Expression Designer, pero todavía no me he puesto con ello) Visual Studio y Expression Blend.

Este último es fundamental para hacerte una idea de cómo va a quedar tu aplicación y os recomiendo encarecidamente que lo utilicéis si disponéis de él (en próximos posts miraremos qué cosas podemos hacer con Blend que no podemos hacer con Visual Studio de forma inmediata).

Bien, pues pongamos un control Panorama en nuestra aplicación. ¿Cómo? La verdad es que lo más fácil es pedirle a Visual Studio que lo haga por nosotros (también podrías hacerlo manualmente). Simplemente, botón derecho sobre la solución -> Add New Item -> Panorama Page.

Nueva Página Panorama

Nueva Página Panorama

Si no lo habías hecho ya cuando creaste la aplicación, sigue estos pasos y podrás écharle un vistazo al (horror) que ha montado Visual Studio. Después, borra casi todo su contenido, para quedarte con lo mínimo.

De momento, voy a montar una página Panorama con el fondo que os indiqué arriba y con tresPanoramaItem

  1. Sitios Favoritos
  2. Sitios Cercanos
  3. Sitios Recientes

En las futuras versiones incluiré algún control más para poder mostrar (probablemente) mis Sitios Favoritos en un mapa de Bing o similar.

Panorama con tres PanoramaItem

Panorama con tres PanoramaItem

Como podéis ver en el código puesto más arriba, he añadido tres PanoramaItem prácticamente idénticos, en este momento sólo se diferencian en el literal (extraído del fichero de recursos de la aplicación) que se mostrará en el texto. Los tres contienen en este momento un ListBox que debería de mostrar elementos del “ViewModel”.

Merece la pena reseñar que, mientras estamos en modo de Diseño (es decir, mientras te encuentras diseñando tu página con la ayuda de Visual Studio o Blend) es interesante que puedas hacerte una idea de qué aspecto tienen los controles que estás montando. Para ello existe una característica muy interesante que te permite definir un contexto de datos en diseño de forma que puedas consumir información en un XML (por ejemplo) que te ayude a hacerte una idea del aspecto de tu aplicación cuando esta contiene información. Dentro de los atributos de una página de Windows Phone es posible definir un Contexto de Datos (DataContext) y que dicho contexto de datos sea utilizado sólo en modo de diseño tal y como se indica a continuación.

Contexto de Datos de Diseño de Página

Contexto de Datos de Diseño de Página

Para crear un contexto de datos en modo diseño podéis revisar este post.

A ver, vamos a intentar dejarlo más claro. Empecemos por las clases que intervienen en el proceso de presentación de la página principal.

Diagrama de Clases para la Presentación de MainPage

Diagrama de Clases para la Presentación de MainPage

Como se ve en la imagen más arriba disponemos de cuatro elementos en juego.

  1. App: Es la clase que representa el contexto o la aplicación que está en ejecución. Contiene (como vimos en el post anterior) los métodos para gestionar el ciclo de vida.
  2. IMainViewModel: Se trata de una interfaz y es un pequeño cambio realizado a la estructura que por defecto presenta Visual Studio. La clase App dispone de una referencia al ViewModel, sin embargo, en mi caso he preferido cambiar el tipo y hacer que la referencia sea a la Interfaz que ha de implementar dicho modelo. De esta forma mejoramos el acoplamiento (reduciéndolo) y favorecemos la posible inclusión de patrones como la Inversión de Control (IoC) aunque en este momento App instancie directamente la clase y todavía no haga uso del patrón.
  3. MainViewModel: Se trata de la VistaModelo para la página principal. Implementa la Interfaz IMainViewModel y, en este momento se trata de una clase que prácticamente hace sólo dos cosas: Definir una lista de elementos (a través de la propiedad Items) y carga dicha lista de elementos (a través del método LoadData).
  4. MainPage: Por último la clase que representa la página en sí misma y que será la Vista de presentación (la que contiene nuestro elemento Panorama). Esta página se comunica con el MainViewModel a través de la interfaz IMainViewModel que expone la clase App cuando la página es cargada (en la gestión del evento Loaded) tal y como se muestra en el diagrama de secuencia a continuación.
MainPage_Loaded

MainPage_Loaded

En breve nos centraremos en el proceso de DataBinding y veremos cómo podemos hacer para realizar filtros de los elementos que componen nuestro conjunto de lugares.

Anuncios

Empezando con Windows Phone 7.1 (y X) – Creando un Contexto de Datos de Prueba con Blend

Cuando comienzas con el diseño de la aplicación es importante tener presente el aspecto que tendrá la misma. Para ello Blend resulta de mucha ayuda.

Mis Sitios Favoritos en Blend

Mis Sitios Favoritos en Blend

Como podéis ver, se muestra una página (en este caso con un control Panorama) y tres PanoramaItem. Dentro de cada uno de ellos existe un ListBox que, actualmente está vacío. Vamos a ver cómo es posible con Blend, crear una fuente de datos de prueba para poder ver el aspecto que tendrá el control en tiempo de diseño.

Para ello abriemos la pestaña Data y, para el proyecto, escogeremos la creación de una nueve fuente de datos a partir de un Objeto (Object Data Source).

Create Object Data Source

Create Object Data Source

La idea es decirle a Blend, que genere un fichero de datos de ejemplo partiendo del ViewModel que tenemos asociado a nuestra página. En mi caso, después de una pantalla de error debida a que estoy utilizando SQL CE en Windows Phone “No se puede cargar el archivo o ensamblado ‘Microsoft.Phone.Data.Internal'” (el ensamblado no está localizado en mi máquina, está dentro del propio teléfono o del emulador. Hablé de ello en este post).

Error Load Microsoft.Phone.Data.Internal

Error Load Microsoft.Phone.Data.Internal

Como decía, después de este bonito error, que podemos ignorar, seleccionamos la clase que implementa el ViewModel para el cual queremos generar el conjunto de datos de ejemplo.

Seleccionar la Clase que implementa el ViewModel

Seleccionar la Clase que implementa el ViewModel

A partir de aquí, es posible editar el fichero XAML que se crea para nutrirlo con datos de ejemplo.

Xaml con datos de ejemplo

Xaml con datos de ejemplo

En Visual Studio, será necesario marcar la propiedad BuildAction del fichero a “DesignData”

BuildAction a "Design Data"

BuildAction a "Design Data"

Y, posteriormente, crear una fuente de datos de diseño que apunte al fichero (yo lo he hecho a nivel de página, pero es posible hacerlo a nivel de control)

Contexto de Datos de Diseño de Página

Contexto de Datos de Diseño de Página

Con este pequeño esfuerzo ya tenemos elementos que pueden mostrarse en pantalla.

Algunos datos en modo diseño

Algunos datos en modo diseño

Ahora queda adaptar un poco el aspecto que tendrá cada elemento, pero esto lo dejaremos para otro post más adelante.

Empezando con Windows Phone 7.1 (y VIII) – El Ciclo de Vida de una Aplicación

Antes de seguir escribiendo más código, es el momento de hacer un alto en el camino para repasar un poco de teoría. Y parece que lo más apropiado (al menos desde mi punto de vista) es comprender primero cuál es el ciclo de vida de una aplicación en Windows Phone: Desde que aprietas el icono en tu lista de aplicaciones o en un “tile” (baldosa) hasta que sales (o crees haber salido) de tu aplicación.

Empecemos con una referencia para contextualizar -> Aquí.

En la primera versión de Windows Phone, el sistema operativo permitía la ejecución de una única aplicación en primer plano en un momento dado. Para facilitarle la vida al programador el S.O. activaba y desactivaba aplicaciones de manera automática pero exponía una serie de eventos que el programador podía manejar  para almacenar y recuperar el estado de la aplicación. Con Mango, el S.O. además mantiene una imagen de la aplicación en memoria tanto tiempo como le sea posible . De esta manera, se crea la sensación para el usuario de que la aplicación continua su ejecución desde el punto donde la dejó la última vez.

Al proceso por el cual el sistema operativo finaliza el proceso asociado a tu aplicación cuando navegas fuera de la misma se le llama “tombstoning” o “tombstone”. Tombstone significa “Lápida” y no quisiera traducir “tombstoning” como lapidar ya que esto último es más bien matar a pedradas, cosa que de momento asumiré que el Sistema Operativo no va a hacer con el proceso de tu aplicación. En cualquier caso, tanto el nombre como la acción, son bastante descriptivas.

El sistema operativo está llevando a tu proceso a mejor vida pero en un estado de “animación suspendida” almacenando información sobre el estado en que quedó la misma (última página de la aplicación y el historial de navegación dentro de la misma). Si decides navegar de vuelta a tu aplicación, el sistema operativo restaura el proceso de la misma y le pasa el estado en que se quedó cuando saliste de ella por última vez.

En Mango, este modelo se mejoró y es conocido como “fast application switching” o “FAS”. Intercambio Rápido de Aplicaciones.

Siguiendo con ello: si quieres controlar este proceso, deberás de manejar los eventos asociados a esta desactivación y posible tombstoning. Generalmente vas a querer mantener información sobre dos cosas:

  1. El Estado de la Aplicación (Application State). Que no se encuentra asociado a ninguna página en particular y que puede gestionarse mediante los eventos que expone la clase PhoneApplicationService. Esencialmente cuatro: Activated, Closing, Deactivated, Launching. Para aquellos que no controlen el inglés, el matiz es importante, cuando se utiliza el pasado, terminado con la partícula “ed” en este caso el significado es que el evento se lanza cuando ha finalizado la acción que maneja el evento. Es decir, en este caso, cuando la aplicación ya se ha activado o ya se ha desactivado. En el caso del gerundio, terminado con la partícula “ing”, el significado es que el evento se está lanzando en algún momento, desde que se comenzó la acción que maneja el evento, pero sin que esta haya terminado todavía. Así, en este caso, los eventos Closing y Launching se lanzan en algún momento antes de que la aplicación termine de cerrarse o antes de que la aplicación termine de estar lista para arrancar.
  2. El Estado de la Página (Page State). Que representa el estado (posición del cursor, información almacenada, etc…) de la página donde quedó la aplicación en el momento del cierre. Normalmente se suele manejar dicho estado desde los manejadores de eventos OnNavigatedTo y OnNavigatedFrom.

Vale. ¿Cómo sé cuándo el sistema operativo va a ponerle la lápida a mi aplicación y cuándo no? Existe alguna regla al respecto, en general supón que ocurrirá siempre que navegues fuera de tu aplicación… Pero, no podía ser de otra manera, existen excepciones.

Imagina que dentro del contexto de tu aplicación (muchas lo hacen) necesitas sacar una foto o video, escoger una imagen de tu biblioteca, seleccionar un contacto de tu agenda, lanzar el reproductor de medios… En, general, realizar una acción que (estando estrictamente fuera de tu aplicación) tiene para el usuario un sentido dentro del discurso de la misma. Bien, en esos casos, el Sistema Operativo no le va a poner la lápida a tu aplicación (tobmstone, ya sabes). Salvo, claro está que se esté quedando sin memoria, en cuyo caso no se va a andar con miramientos, compréndelo.

Bien. Momento de tomar un respiro y ver si hemos digerido lo anterior.

¿Lo tienes? Bien, sigamos pues que ya queda poco.

Cuál es entonces el ciclo de vida de una aplicación. Pues voy a poner mi versión de un gráfico que he visto por ahí en varios sitios, no porque me sienta original, simplemente porque se entiende mejor cuando intentas hacer un blog en español.

Windows Phone Application Lifecycle

Ciclo de vida de una aplicación en Windows Phone

Si no le has echado un vistazo al artículo que enlacé al comienzo, hazlo ahora. Encontrarás una diferencia importante entre los diagramas que se pintan ahí y el que he pintado aquí. Esencialmente el diagrama en el artículo de la MSDN distingue entre dos estados (no transiciones) de “desactivación” de tu aplicación. En el que el sistema operativo mantiene tu aplicación en memoria (un durmiente, dormant) y en el que lo ha enterrado y puesto la lápida (tombstone).

En esta entrada he preferido no hacer la distincion ya que no tienes forma de saber cuándo el sistema operativo va a realizar a ciencia cierta la operación de tombstone, así que prepárate para ella y te curarás en salud.

Bien, espero que con esto quede claro. A mi, desde luego, me ha ayudado aunque es probable que tenga que repasar algún que otro concepto más antes de seguir adelante con la aplicación.

Empezando con Windows Phone 7.1 (y V) – Soportando varios idiomas

Uno de los primeros pasos que he realizado ha sido dotar a la aplicación de infraestructura necesaria para dar soporte a múltiples idiomas. Esto no significa que la aplicación salga inicialmente soportando varios idiomas, significa que, cuando haya que hacerlo, los cambios que tendré que llevar a cabo serán mínimos.

Imaginad que comenzáis creando una aplicación sin tener esto en cuenta. Cada uno de los literales que introduzcas en tu código (y no me limito únicamente a los que aparecen en la capa de presentación) estarán mejor o peor organizados, pero probablemente dispersos por todo tu código.

Cuando llegue el momento de dar soporte a varios idiomas, tendrás que empezar a buscar estos literales por toooodo tu código, sacarlos a ficheros de recursos y, una vez ahí, comenzar con el proceso de prueba /error hasta que estés seguro de que lo has contemplado todo. A partir de este punto, podrás comenzar a añadir más ficheros de rescursos que den soporte a diferentes idiomas.

Mi aproximación es diferente. He creado la infraestructura necesaria para dar este soporte desde el comienzo. Ahora lo que hay que contar es con la disciplina suficiente como, cada vez que necesites crear un nuevo literal, hacerlo en el fichero de recursos en vez de directamente en tu código.

Ficheros de Recursos en el Proyecto

Varios ficheros de recursos añadidos al Proyecto

A continuación he configurado el idioma neutral del proyecto para que sea el español (de España).

Idioma Neutral por defecto

Configuración del Idioma Neutral para que sea español (España)

Una cosa que me ha llamado la atención es la siguiente: Para indicar qué idiomas soporta la aplicación, es necesario editar el fichero .csproj para indicar dentro del tag <SupportedCultures/> qué idiomas soporta la aplicación. Este fichero tiene un formato XML, sin embargo, abrir el XML en vez del proyecto no es tarea fácil dentro de Visual Studio. Así que he abierto mi fichero con Notepad++ y he introducido dentro de dicho tag (de momento) sólo el español. He guardado, recargado el proyecto en Visual Studio y… Ya está, mi aplicación dice que soporta el español. Para el inglés queda un poquito (tendré que acordarme de separar los idiomas con puntos y comas).

SupportedCultures en el proyecto

Elemento <SupportedCultures/> en el proyecto

En relación a la inclusión de ficheros de recursos, la idea es buena, pero las prisas, el cansancio o la inexperiencia pueden hacer que olvides incluir literales en tus ficheros y sigas metiéndolos en código. ¿Qué hacer en este caso? Pues habrá que mirar Code Analysis. Eso haré y os tendré al tanto.

Empezando con Windows Phone 7.1 (y II) – Definición del Backlog

Que no parezca que me estoy demorando más de la cuenta en empezara a meterle mano al código… Estuve montando el entorno (sin comentarios dignos de mención: siguiente – siguiente – siguiente). Y el resultado es que ya tengo el IDE operativo para empezar a trabajar con Windows Phone.

El siguiente paso es ver qué queremos hacer. Creo que un Hola Mundo! puede aportar más bien poca cosa, así que vamos a ser valientes y comenzaremos con algo más ambicioso.

Para darle un poco más de sentido a todo esto voy a intentar hacer uso de algunas buenas prácticas de Metodologías Ágiles (os recomiendo echar un vistazo al blog de El Bruno para empezar por algo bueno). Si os atrevéis con el inglés, os pongo un enlace a un documento interesante (de Leonard Woody) que explica el proceso guiado, paso por paso, de tareas, actividades y procesos a tener en cuenta en un proyecto en el que se haga uso de la metodología ágil Microsoft Solution Framework for Agile Development v5.0

Así que, en eso estamos. Vamos a empezar pensando qué es lo que quiero que haga mi nueva aplicación. Como el objetivo es aprender (y no hacerme rico con una aplicación rompedora, aunque tampoco le haría feos a eso) los requerimientos que voy a poner sobre la mesa van a estar más orientados a mis objetivos de aprendizaje que a la funcionalidad de la aplicación.

A esta lista de requisitos, en términos de metodologías ágiles, nos podemos referir de varias formas (History List, Product Backlog, etc…) dependerá de la metodología que escojas. En mi caso, todavía no lo he decidido pero estoy dándole alguna vuelta al respecto. Os mantendré actualizados. De momento, he aquí la lista de funcionalidades con las que me gustaría jugar en Windows Phone 7.1.

Backlog

El siguiente paso es empezar con cierto realismo. Al fin y al cabo estoy yo solo, así que la velocidad de mi equipo (es decir, yo) probablemente sea muy baja. Empecemos con objetivos realistas y luego. ¡Cambiemos de opinión! Al fin y al cabo así es como funcionan las cosas. ¿No?

Nos vemos en el siguiente artículo.