Windows Phone 8 SDK Preview announced for September 12th, public release “later this year”

Mientras tanto, iré esperando pacientemente para poder seguir programando mi Windows Phone sobre Windows 8 y Visual Studio 2012.

Por otro lado, así aprovecho para aprender algunas cosas sobre la programación de aplicaciones para el Store de Windows 8.

Ya os contaré.

Anuncios

Empezando con Windows Phone (y XII) – Iconos, Botones y Metro Studio

¿Para qué?

Llegado a este punto, me queda asignar cierta lógica a la interfaz de alta de nuevos lugares. Actualmente (por poco tiempo, espero) se encuentra dentro del ModeloVista de la página principal, en breve se convertirá en una página aparte (momento en que aprovecharé para trastear un poco con la navegación).

Asignando Comandos a un Botón (al estilo MVVM)

La interfaz de alta de nuevos lugares es muy sencilla:

  1. Un bloque de texto que indica que este es el sitio de tu aplicación preparado para el alta.
  2. Un cuadro de texto encargado de recoger el nombre del nuevo lugar.
  3. Un botón para crear el nuevo lugar.

Para el botón, simplemente he enlazado el Comando al creado en la VistaModelo y, como parámetro, el texto de la caja de texto que se utiliza para crear el nombre del nuevo lugar. Así:

 1: <Button

 2:     Command="{Binding Path=CrearNuevoLugar}"

 3:     CommandParameter="{Binding ElementName=NuevoLugarTextBox, Path=Text}"

 4:

 5:     Margin="0,0,0,0"

 6:     x:Name="NuevoLugarBtn"

 7:     Grid.Row="2"

 8:     Content="{Binding LocalizedResources.TituloBotonNuevoLugar, Source={StaticResource LocalizationHelper}}"

 9:     ClickMode="Press"

 10:     Background="{StaticResource PhoneBackgroundBrush}"

 11:     BorderBrush="{StaticResource PhoneBorderBrush}"

 12:     Foreground="{StaticResource PhoneForegroundBrush}"/>

El “Binding” está realizado contra la propiedad “CrearNuevoLugar” que está expuesta en la vista.

 1: public class MainViewModel : IMainViewModel

 2: {

 3:     public MainViewModel()

 4:     {

 5:         _comandoCrearLugar = new DelegateCommand(AccionCrearNuevoLugar, PuedeCrearNuevoLugar);

 6:         _nombreNuevoLugar = Resources.MisSitiosFavoritosResources.TextoNuevoLugar;

 7:

 8:         ActualizarVistas();

 9:     }

 10:

 11:     public ICommand CrearNuevoLugar

 12:     {

 13:         get { return _comandoCrearLugar; }

 14:     }

 28: }

Por último, el comando delega la funcionalidad en dos métodos de la propia vista (AccionCrearNuevoLugar y PuedeCrearNuevoLugar). El primero se encarga de crear un nuevo lugar, el segundo se utiliza para determinar si dicha acción puede llevarse o no a cabo.

 1: private void AccionCrearNuevoLugar(object nuevo)

 2: {

 3:     if (nuevo == null)

 4:         throw new ArgumentException("nuevo");

 5:

 6:     var sNuevo = nuevo.ToString();

 7:     MiLugar nuevoLugar = Logica.NuevoLugar(sNuevo, string.Empty);

 8: }

 9:

 10: private bool PuedeCrearNuevoLugar(object nuevo)

 11: {

 12:     var result = false;

 13:     if (nuevo != null)

 14:     {

 15:         string sNuevo = nuevo.ToString();

 16:

 17:         result = !String.IsNullOrEmpty(sNuevo) && (String.Compare(sNuevo, Resources.MisSitiosFavoritosResources.TextoNuevoLugar) != 0);

 18:     }

 19:

 20:     return result;

 21: }

Ambos métodos recogen como parámetro el nombre del nuevo lugar. Uno de ellos se limita a crear una instancia del nuevo lugar, el otro comprueba el nombre (asegurándose de que no está vacío y que, además, no es la cadena de texto por defecto que se muestra en el control).

Lo bonito de esta aproximación es lo siguiente:

  1. Nada de código en un manejador de eventos que se dispara cuando se presiona el botón.
  2. De nuevo el Modelo-Vista no sabe absolutabmente nada de la vista y, con la ayuda de la clase DelgateCommand la lógica correspondiente al comando sigue dentro del Modelo-Vista.

Bueno, no mucho más que decir. Ahora a crear el botón.

Creando un botón (feo) y otro (menos feo) con Metro Studio

Ha llegado el momento de tener lista la interfaz para dar de alta un nuevo lugar (en este momento no está separada de la vista principal, pero en breve lo estará).

El primer intento consistió en añadir un simple botón con un texto en su interior.

image

Como podéis ver, se trata de un horrible botón que me permite dar de alta un nuevo lugar de forma bastante sencilla utilizando DataBinding.

En esta primera versión voy a reemplazar dicho botón por otro con un estilo visual más cercano a Metro. Para ello voy a utilizar una herramienta gratuita de Syncfusion llamada Metro Studio.

Metro Studio es una colección de iconos completamente gratuitos que siguen las normas de estilo y diseño de la interfaz Metro (la propia interfaz de la herramienta sigue dichas normas). Es muy sencilla de utilizar.

image

Simplemente busca iconos en el buscador o utilizando las categorías.

image

Selecciona tu icono (en mi caso, un original “Save”) y edítalo haciendo uso de una herramienta muy sencilla.

image

Finalmente puedes optar por almacenar el XAML generado por la herramienta.

image

O bien, obtener una imagen de la misma en tu formato preferido.

image

El resultado: algo igual de feo y que habrá que cambiar: Crear una nueva vista con su página correspondiente y, probablemente, una barra de herramientas con la botonera correspondiente.

image

 1: <controls:PanoramaItem Header="{Binding LocalizedResources.TituloNuevoSitio, Source={StaticResource LocalizationHelper}}" Orientation="Vertical" Foreground="{StaticResource PhoneBackgroundBrush}">

 2:     <Grid x:Name="LayoutForm" Background="Transparent">

 3:         <Grid.RowDefinitions>

 4:             <RowDefinition Height="Auto"/>

 5:             <RowDefinition Height="Auto" />

 6:             <RowDefinition Height="Auto"/>

 7:         </Grid.RowDefinitions>

 8:

 9:         <TextBlock Height="45" Margin="0,0,0,0" TextWrapping="Wrap" Text="{Binding LocalizedResources.TituloTextoNuevoLugar, Source={StaticResource LocalizationHelper}}" VerticalAlignment="Top" Width="400" Grid.Row="0" />

 10:         <TextBox Margin="0,0,0,0" x:Name="NuevoLugarTextBox" Text="{Binding Path=NombreNuevoLugar}" Style="{StaticResource LugarTextBox}" Padding="0,0,0,0" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" Grid.Row="1" />

 11:         <Button Margin="0,0,0,0" x:Name="NuevoLugarBtn" Command="{Binding Path=CrearNuevoLugar}" CommandParameter="{Binding ElementName=NuevoLugarTextBox, Path=Text}" Grid.Row="2" ClickMode="Press" Height="96" Width="96" HorizontalAlignment="Right">

 12:             <Button.Background>

 13:                 <ImageBrush ImageSource="Resources/images/SaveButton.png"/>

 14:             </Button.Background>

 15:         </Button>

 16:     </Grid>

 17: </controls:PanoramaItem>

Eso sí, tendrá que ser en el próximo post.

Winking smile

Nueva aplicación de Skydrive y actualización de Espacio

Tal y como me comentaba mi amigo Danann, recientemente ha sido publicada en Internet una nueva aplicación para Skydrive (la podéis encontrar aquí). La versión para escritorio te crea una carpeta en “Favoritos” donde puedes sincronizar tus carpetas de Skydrive como si fuera una carpeta en PC (aplicación que, por otro lado, ya estaba presente en otras soluciones como Dropbox).

image

Hasta el momento yo utilizaba LiveMesh (parte del paquete Essentials) y, seguiré usándolo porque me parece (al menos de momento, más flexible, aunque menos intuitiva). LiveMesh me permite sincronizar no sólo en Skydrive, también entre diferentes máquinas así cómo acceder por escritorio remoto fácilmente entre ellas.

Bien, en cualquier caso, vamos al motivo de este post. Cuando mi aplicación de Windows Phone se actualizó, entré para echarle un vistazo a los cambios y, desde el menú de configuración pude ver que disponía de 7GB de espacio en Skydrive. ¡¡¿¿7GB, pero no eran 25GB??!!

Es el momento de echarle un vistazo a tu cuenta de Live! y acceder a Skydrive

image

En la parte inferior izquierda podrás ver el menú de administrar almacenamiento

image

Una vez accedas, actualiza gratuitamente tu espacio en cuenta de 7GB a 25GB. Microsoft dice que es por tiempo limitado, asi que no esperes… No vaya a ser.

image

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 VI) – El Contexto de Datos

En esta primera aplicación, estoy creando un modelo de datos muy sencillo: esencialmente se trata de una colección de lugares de interés para el usuario. Poco más que añadir en esta primera iteración ya que, de momento, no daré soporte anidamientos y no habrá relaciones con otras entidades (al menos no las he identificado todavía). Queda para más adelante anidar lugares dentro de lugares y relacionar lugares con personas.

Para la creación del modelo de datos he comenzado con la entidad principal MiLugar: Se trata de una clase muy sencilla que proporciona dos propiedades. un identificador único y un nombre.

Entidad MiLugar en Iteración 1

Entidad MiLugar en Iteración 1

Caben destacar muy poquitas cosas de la entidad:

  1. Implementa la interfaz INotifyPropertyChanged que es de gran utilidad para comunicar cambios en propiedades de la entidad (una buena forma de que, por ejemplo, una vista sepa que la propiedad que tiene asociada a, digamos por ejemplo, un campo de texto ha cambiado y que, en consecuencia, ha de redibujar dicho campo de texto para mostrar el cambio). Veréis más adelante que esta interfaz está en el corazón de la forma en la que se asocian datos y vistas (llamadlas pantallas, si queréis).
  2. Que la entidad ha sido decorada con el atributo TableAttribute y que ambos campos han sido decorados, a su vez con el atributo ColumnAttribute. De esta manera estamos estableciendo las reglas con las que el contexto de datos podrá crear su implementación física a partir de la definición de mi entidad.
DetalleCodigoMiLugar_Iteracion1

Detalle de la entidad MiLugar en Iteración 1: Atributos Table y Column.

Como veis no tiene gran cosa (el código que veis aquí aun no ha sido probado, así que cruzo los dedos para que no me de ningún susto).

Actualización: Cabe decir que el código reflejado ahí arriba compila, pero no funciona en Windows Phone. ¿La razón? El tipo GUID no existe en SQL Server CE, poned en cambio uniqueidentifier y todo irá como la seda.

El siguiente paso es crear la clase encargada de representar el contexto de datos.

DataContext_Iteracion1

Diagrama de clases para el Contexto de Datos en Iteración 1

En este caso se trata de una clase que implementa el patrón Singleton y hereda de la clase DataContext. La única instancia del contexto de datos se puede obtener a través de la propiedad Instancia y contiene una colección de MiLugar que representamos como una propiedad de la clase Table (LugaresDeInteres).

En general, el contexto de datos tiene como propósito abstraernos de los detalles de acceso de la base de datos, limitándose a proporcionar colecciones (tablas) de entidades y mecanismos para buscar, insertar, editar y borrar elementos de dichas colecciones. En ningún momento nuestro código conocerá una sola línea orientada a abrir, crear, consultar o actualizar una base de datos.

Como podéis ver, el proceso de creación de la instancia de DataContext es bastante sencillo. Se pretende garantizar la concurrencia de hilos (cosa que, en esta aplicación será muy sencillo). A continuación, una implementación típica de Singleton y un pequeño detalle. Si la base de datos no ha sido creada todavía: la creamos mediante la línea _dataContext.CreateDatabase (); Fijaos que la cadena de conexión nos indica que la base de datos se referenciará en nuestro Almacén Aislado (IsolatedStorage)

DetalleInstanciaDataContext_Iteracion1

Detalle de la instanciación del DataContext en Iteración 1

A continuación, vamos a llevarnos el contexto de datos hacia arriba en nuestras capas de aplicación. La idea es utilizarlo en nuestras pantallas y, para eso, vamos a aprovechar la infraestructura que crea Visual Studio 2010 para implementar un patrón de capa de presentación llamado Modelo Vista – Vistamodelo (MVVM: Model view – ViewModel). Probablemente le dedique alguna entrada a este patrón, pero no ahora que todavía no lo tengo demasiado claro. Un par de trazos: los patrones de diseño para la capa de presentación llevan dando vueltas por ahí décadas. En un patrón típico Modelo Vista Presentación tienes lo siguiente:

  1. La Vista: Puedes asemejarla sin problemas a tu pantalla
  2. El Modelo: Los datos que se muestran en la vista.
  3. La Presentación: Lo que junta ambas cosas (definición donde las haya. ¿Eh?)

El MVVM es un patrón específico para Windows Presentation Foundation (WPF) que, os recuerdo, es un superconjunto de Silverlight que es con lo que montáis vuestras pantallas en Windows Phone.

Si no os parece mal, dejaremos la capa de presentación y su asociación con los datos para la siguiente entrada.