Mi primera aplicación en MetroUI

Muy buenas! Como muchos otros he descargado el Windows 8 Developers Preview, y he empezado a jugar con la nueva API de WinRT para la creación de aplicaciones basadas en MetroUI.

Vamos a ver como realizar una aplicación MetroUI usando C# que simplemente nos muestre las imágenes que tenemos en la carpeta de “Mis Imágenes”.

Para ello, abrimos el Visual Studio 2011 Express que viene con el Windows 8 Developers Preview y seleccionamos el tipo de proyecto de tipo “Windows Metro Style –> Application”:

image

Con eso VS2010 nos genera el esqueleto del proyecto inicial.

¡Hey eso es WPF!

Pues no. Aunque sin duda se le parece mucho. Veamos, por un lado tenemos la definición de la interfaz en XAML. Si tecleamos un poco, vemos que nuestros controles de WPF (o Silverlight) están aquí:

image

Tenemos TextBlock, Button, Grid, StackPanel… con las mismas propiedades y las mismas extensiones de XAML que nos podemos encontrar en WPF. Si no son las mismas son muy, muy parecidas. Y esa es la primera lección que extraemos: el conocimiento que hemos adquirido desarrollando con WPF o Silverlight no está perdido. Así pues, tranquilos por este lado: no empezamos de cero!

En mi caso he diseñado una página muy cutre que se compone básicamente de un botón, una etiqueta y una lista. Cuando se pulse el botón la lista debe mostrar los nombres y un thumbnail de las imágenes que tenemos en “Mis Imagenes”. Esa es la idea. La definición de la vista es muy simple:

image

Los que hayáis desarrollado en WPF o Silverlight no veréis nada nuevo. Insisto, todos los conceptos que conocemos están aquí. Estilos, recursos, templates, bindings… Todo funciona exactamente igual.

WinRT la nueva API que está detrás…

Aunque este XAML parezca de WPF o Silverlight, realmente no estamos usando WPF ni Silverlight. Eso significa que por detrás, es decir en el código C#, tenemos una nueva API que si que nos va a tocar aprender a utilizar… Pero es que si no… donde estaría la diversión?

Bueno, veamos lo primero que quiero es recorrer las imágenes de la carpeta de “Mis Imagenes” cuando se pulse el botón. Eso, hasta ahora, lo conseguiría usando el método GetFiles de la clase System.IO.Directory, p.ej. Ahora, no: olvidaos de todo esto. De hecho, si en el código C# tecleáis System.IO:

image

veréis que NO sale la clase Directory. No existe! Podéis pensar que a lo mejor falta alguna referencia, pero no… Simplemente no tenemos disponible esta clase. Así que debemos usar la nueva API WinRT que se encuentra colgando del namespace Windows.

Y esa nueva API tiene una característica muy especial: está diseñada de un modo muy asíncrono. Muchas de sus clases tienen métodos cuyo nombre termina en Async() y que son asíncronas. Por suerte en C#5 vamos a disponer de las palabras clave async y await que hacen que llamar a métodos asíncronamente sea lo más fácil del mundo. Ya veréis vais a usar await y async constantemente…

Bien, a lo que íbamos, cuando se pulse el botón quiero que:

  1. El TextBlock de estado diga “Obteniendo”.
  2. Se obtengan las imágenes que hay en mis imágenes.
  3. Y se enlacen con la ListBox para que se muestren.

Y el código es el siguiente:

image

Veis lo que os decía de async y await? Bueno… a ver, este código es muy simple, lo que hace es lo siguiente:

  1. Pone el texto “Obteniendo” en nuestro TextBlock de estado
  2. Llama al método DisplayImagesAsync(). Método que se ejecutará asíncronamente.
  3. Cuando el método termine, se ejecutará el código que está a continuación del await, es decir pondrá el TextBlock a blanco, para indicar que ya ha terminado.

En este caso, realmente no hay asincronidad. Me explico: el método DisplayImagesAsync() está pensado para que pueda ser usado asíncronamente, pero nosotros no hacemos nada entre que llamamos el método y nos esperamos (await) a que termine. Si entre la línea var displayImagesTask = DisplayImagesAsync() y la siguiente (await displayImagesTask) yo hubiese colocado código, este código se ejecutaría en paralelo al código del método DisplayImagesAsync(). Esta es la potencia brutal de async/await: facilitan hasta el absurdo la creación de métodos que pueden ser invocados asíncronamente y la espera para que terminen esos métodos.

Bueno… veamos el método DisplayImagesAsync(). Para empezar dicho método debe obtener acceso a la carpeta de “Mis Imagenes”. Para ello usamos la clase KnownFolders de Windows.Storage:

image

Con eso en picsFolder tenemos un objeto que nos permitirá recorrer la carpeta de “Mis Imágenes”. Para ello tiene un método GetItemsAsync() que nos devuelve una lista con todos los elementos. Así que, lo invocamos:

image

Esta forma de usar await es muy común y en el fondo es lo mismo que hemos hecho antes (cuando hemos llamado a DisplayImagesAsync) pero en una sóla linea: invocar el método asíncrono, esperarnos a que termine y en pics tenemos el resultado 🙂

Este resultado es un enumerable con todos los items de la carpeta. Eso incluye ficheros y directorios. Lo que vamos a hacer ahora es iterar por todos los ficheros y por cada fichero obtener un thumbnail junto con su nombre y su ruta:

image

Listos! Con esto rellenamos la lista images (una lista dinámica) con los datos (nombre, ruta y thumbnail) de las imágenes que tengamos. Nos queda una pieza para verlo todo y es el método GetBitmapData.

El método GetThumbnailAsync no devuelve directamente un bitmap con el thumbnail, sino que devuelve un objeto (de la clase StorageItemThumbnail) a partir del cual podemos obtener un stream a los datos que representan el bitmap del thumbnail. Pero nosotros queremos algo que sea un ImageSource (para enlazarlo a la propiedad Source del DataTemplate de la ListBox). Y eso que necesitamos es un objeto de la clase BitmapImage. Por suerte es muy fácil obtener un BitmapImage a partir de un StorageItemThumbnail:

image

Y listos! Con esto lo tenemos todo ya hecho… sólo nos queda enlazar la lista images con nuestra ListBox, y eso lo conseguimos con este código (al final de DisplayImagesAsync), que resultará muy familiar a quien haya desarrollado con WPF o Silverlight:

image

Y listos! Con esto conseguimos mostrar las imágenes que tenga el usuario en la carpeta “Mis Imágenes”:

image

Hemos realizado nuestra primera aplicación MetroUI! 🙂

Ah sí! Permisos, permisos, permisos

Que me olvido! Las aplicaciones MetroUI tienen asignado un sistema de seguridad, donde tienen que declarar exactamente que permisos necesitan. Esos permisos se mostraran al usuario cuando este quiera ejecutar la aplicación (o la compre desde el nuevo Windows Store). Para ello es necesario editar el archivo Package.appxmanifest y allí poner los permisos necesarios. Visual Studio 2011 viene con un editor para este archivo. En nuestro caso, debemos pedir específicamente permiso para acceder a la carpeta de imágenes del usuario:

image

Tenemos que ir a “Capabilities” y marcar la checkbox de Picture Library Access.

Ahora sí, que ya lo tenemos todo! 😉

Un saludo!

PD: El código en este post son imágenes porque estoy posteando desde el propio Win8 y no tengo ningún plugin de código instalado en el Live Writer

PD2: He dejado el proyecto (de Visual Studio 2011 Developers Preview) en mi carpeta de skydrive. Lo podeís descargar desde aquí: MyFirstApp (código fuente)

PD3: No toméis esa aplicación como una guía de buenas prácticas ni nada parecido! Este post es simplemente para compartir mi experiencia de “desvirgamiento” en WinRT 😛 😛 😛

Un comentario sobre “Mi primera aplicación en MetroUI”

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *