Taller W8: Desarrollando mi primera App para Windows 8 con C#


En esta articulo les comparto el tutorial que presente en el taller impartido en #CampusPartyMX4 esperando les agrade tanto como a mi a la hora de crearlo.

“Medir el progreso del desarrollo de software por líneas de código es como medir el progreso de la construcción de un avión por su peso”
— Bill Gates

El siguiente material se creó con la finalidad de enseñar a desarrollar una aplicación desde 0 para el nuevo sistema operativo de Microsoft: Windows 8.

Antes de empezar se debe dejar bien claro que NO se pueden crear Apps para Windows 8 si no se cuenta con este SO instalado en la máquina, además se debe de contar previamente con: Visual Studio 2012

Una vez teniendo todo instalado, procedemos a generar un nuevo Proyecto, tal y como se muestra en la siguiente imagen:

1

Nos desplegara la siguiente imagen, en donde nos mostrara un listado de tipos de plantillas que tenemos para seleccionar, para este Demo elegiremos la que se llama “Aplicación de  cuadricula (XAML)”, le proporcionaremos un nombre y proporcionaremos la ruta en donde se guardara.

2

Aplicación de Cuadricula (XAML)
Proyecto de tres páginas de la Tienda Windows que navega entre elementos agrupaos organizados en una cuadricula. Las páginas dedicadas muestran detalles del grupo y de los elementos.

Si quieres conocer los distintos tipos de plantillas entra al siguiente enlace:
Plantillas de proyecto C#, VB y C++ para aplicaciones de la Tienda Windows

Una vez que le demos al botón de Aceptar tendremos una pantalla similar a esta:

3

Antes de comenzar a aventar código, identifiquemos las partes más importantes de nuestro ambiente de trabajo para familiarizarnos.

Compilación

Para poder ejecutar nuestro proyecto tenemos primero que compilarlo, esto se puede de realizar de distintas formas.
En nuestra barra de controles accedemos a “Compilar” y enseguida aparecerá la opción de “Compilar Solución”, de igual forma nos muestra la forma de hacerlo presionando al mismo tiempo la combinación de teclas: Ctrl + Mayus + B, aunque en algunas máquinas no puede funcionar esta combinación, les sugiero intenten Ctrl + Shift + B.

Cabe destacar que conforme vayamos creando o editando algunas partes, estas no se “empatan” con la solución, para esto también contamos con la opción de “Limpiar Solución”.

En mi experiencia siempre limpio y compilo antes de ejecutar la aplicación.

4

Después de haber realizado lo anterior, en la parte superior un botón de “play” el cual nos marca por default “Equipo Local”, esto significa que la aplicación se ejecutara en nuestra máquina.

Nota// Se necesita tener Windows 8, en caso contrario, teniendo esta opción activa no funcionara.

5

Además de poder ejecutar la App de manera local, el SDK de Visual Studio nos brinda la opción de compilar en un Simulador o en un Equipo remoto.
Estas dos últimas opciones las conoceremos en el siguiente tutorial

6

También debemos de conocer la diferencia entre las modalidades de compilación, las cuales son solo dos: Debug & Release

Debug: esta versión del programa se compila sin optimizar y con toda la información de depuración simbólica. La optimización complica la depuración, ya que la relación entre el código fuente y las instrucciones generadas es más compleja.

Release: esta versión del programa no contiene información de depuración simbólica y está totalmente optimizada. La información de depuración se puede generar en Archivos PDB (C++), según las opciones del compilador utilizadas. Crear archivos PDB puede ser muy útil si luego necesita depurar la versión de lanzamiento.

En otras palabras la versión de depuración se genera para la depuración y la versión de lanzamiento para la distribución final de lanzamiento.

7

Explorador de Soluciones

En el explorador de soluciones es donde se encuentra todo lo relacionado a nuestro proyecto, desde las Referencias, Imágenes y clases.
Aquí podemos ver desde la vista diseño y el código de cada página o elemento.

GroupedItemsPage.xaml (Design)
GroupedItemsPage.xaml.cs (Code)

8

Abramos la página de GroupedItemsPage, la cual es la principal de nuestro proyecto.
Ahora compilemos nuestro proyecto para poder ver como se encuentra actualmente y comprobar que no existe ningún error.

9

En este tutorial veremos cómo crear una App que consume un Feed, y para este demo utilizaremos el de este portal:

http://geeks.ms/blogs/MainFeed.aspx

Nota//

Para que tu App sea una que se mantenga sola debes de ver que el sitio que quieras utilizar muestre la siguiente información:

Está viendo una fuente cuyo contenido se actualiza con frecuencia. Las fuentes se agregan a la lista de fuentes comunes cada vez que se suscribe a ellas. La información actualizada en la fuente se descarga automáticamente en el equipo y se podrá consultar en Internet Explorer y en otros programas.

Lo primero que editaremos será el archivo de la página “GroupedItemsPage.xaml.cs”, en el método LoadState.

Antes:

10

Lo que haremos será decirle al método de carga que añada y muestre todos los elementos que se puedan extraer del elemento que se encuentra en el “SampleDataSource”, en este caso será AllGroups.

Despues:

protected override async void LoadState
(Object navigationParameter, Dictionary<String, Object> pageState) {

this.DefaultViewModel[“Groups”] = SampleDataSource.AllGroups;
await SampleDataSource.AddGroupForFeedAsync(“http://geeks.ms/blogs/MainFeed.aspx&#8221;); } 

SampleDataSource: Crea una colección de grupos y elementos con contenido codificado de forma rígida. SampleDataSource se inicializa con datos marcadores de posición en lugar de con datos de producción activos, por lo que se proporcionan datos de muestra tanto en el momento del diseño como en el de la ejecución.

Ahora abriremos el elemento “SampleDataSource.cs” que se encuentra en la carpeta DataModel.

11

Referencias faltantes.

Las referencias son muy importantes a la hora de la creación de algunos métodos y eventos, es por eso que se deben de agregar si se conocen, en caso contrario se pueden añadir después.

Las que ya se encuentran importadas en nuestro archivo son las siguientes:

using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Windows.ApplicationModel.Resources.Core;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using System.Collections.Specialized;

Y las que añadiremos serán las siguientes:

using System.IO;
using System.Text.RegularExpressions;

Cuando nos haga falta alguna referencia, al momento de compilar el mismo Visual Studio nos indica cual es la que no se encuentra.

Por ejemplo:

12

Solo es cuestión de dar doble click al error y este nos llevara a la línea exacta en el código.

Para poder solucionarlo,  solo es de posicionar el cursor en la palabra “Task” y cuando nos aparezca un cuadrito seleccionamos la primera opción:

using.System.Threading.Tasks;

13

Para resolver el segundo error, repetimos el mismo procedimiento, solo que aquí la referencia que nos hace falta es la de: using Windows.Web.Syndication;

14

Y así luce nuestro archivo con todas las referencias:

15

Busquemos la clase sellada SampleDataSource, veremos que contiene una instancia de la misma.
public sealed class SampleDataSource
{
private static SampleDataSource _sampleDataSource = new SampleDataSource();

Lo que haremos ahora será agregar una colección de objetos SampleDataGroup arriba de la instancia a la que llamaremos AllGroups, la cual ocuparemos más adelante.

public static readonly ObservableCollection<SampleDataGroup> AllGroups =

new ObservableCollection<SampleDataGroup>();

Las lineas siguientes:

private ObservableCollection<SampleDataGroup> _allGroups = new ObservableCollection<SampleDataGroup>();

public ObservableCollection<SampleDataGroup> AllGroups
{
get { return this._allGroups; }
}
public static IEnumerable<SampleDataGroup> GetGroups(string uniqueId)
{
if (!uniqueId.Equals(“AllGroups”)) throw new ArgumentException(“Only ‘AllGroups’ is supported as a collection of groups”);

return _sampleDataSource.AllGroups;
}

Las eliminamos, ya que no las utilizaremos.

Y en las métodos de GetGroup y GetItem lo único que haremos será idenficar “_sampleDataSource” y lo borramos, para dejar la validación de AllGroups.

16

Así nos debe de quedar hasta el momento:

17

Ahora si observamos la clase publica de SampleDataSource contiene 6 grupos de ítems ya definidos por la aplicación, lo que haremos ahora sería cargar los ítems propios de la página que vamos a leer, en este caso el del Feed, para ello vamos a limpiar el método “SampleDataSource”, en otras palabras eliminar todo su contenido.

18

Después:

public SampleDataSource()
}

Para llenar el SampleDataSource vamos a crear un método asíncrono que permita obtener los ítems de la URL, el cual se llamara “AddGroupForFeedAsync”, cuyo parámetro de entrada será la cadena de la URL a leer.

Para los que no sepan que es un método asíncrono, este funciona de modo que se obtienen los datos en una consulta y se refrescan hasta que se genera una nueva.

public static async Task<bool> AddGroupForFeedAsync(string feedUrl)

{
}

Dentro de este método evaluaremos si es posible obtener el grupo de ítems de nuestra URL, en caso correcto se crearan 2 variables: feed y feedGroup.

if (SampleDataSource.GetGroup(feedUrl) != null) return false;

var feed =
var feedGroup =

La variable feed inicializara un objeto del tipo SyndicationClient para obtener los ítems de la URL. Y la variable feedGroup inicializara un SampleDataGroup que valida los campos de título, subtitulo e imagen.

var feed = await new SyndicationClient().RetrieveFeedAsync(new Uri(feedUrl));

var feedGroup = new SampleDataGroup(uniqueId: feedUrl,

title: feed.Title != null ? feed.Title.Text : null,

subtitle: feed.Subtitle != null ? feed.Subtitle.Text : null,

imagePath: feed.ImageUri != null ? feed.ImageUri.ToString(): “/Assets/Logito.jpg”,

description: null);

En el campo de imagePath realizamos una simple validación en donde si la nota creada no tiene imagen o no puede ser mostrada (esto puede ser afectado por su formato o resolución) mostraremos una local.

Hecho esto recorreremos los ítems de nuestra variable feed para cargar los elementos.

foreach (var i in feed.Items)
{  }

Para esto manipularemos la cadena denominada imagePath, la cual es igual al método GetImageFromPostContents que crearemos más adelante.

string imagePath = GetImageFromPostContents(i);

A continuación validaremos el valor de la cadena, en donde si es igual a nulo y el elemento de imagen del grupo también, mostremos una imagen definida por nosotros, esto para que no quede vacío a la hora de ejecución.

if (imagePath == null && feedGroup.Image != null)

imagePath = “/Assets/Logito.jpg”;

Después los asignaremos a nuestro feedGroup.

feedGroup.Items.Add(new SampleDataItem(

uniqueId: i.Id, title: i.Title.Text, subtitle: null, imagePath: imagePath,

description: null, content: Windows.Data.Html.HtmlUtilities.ConvertToText(i.Summary.Text), @group: feedGroup));

Ahora se procede a cargar el feedGroup creado en la vista de la aplicación, el cual es AllGroups.

AllGroups.Add(feedGroup);

return true;

Ya para culminar crearemos un método en el cual obtendremos el formato de las imagenes que contiene el Feed,  y también limpiaremos el contenido (caracteres Unicode) que nos arroje el texto del mismo.

private static string GetImageFromPostContents(SyndicationItem item)
{
return Regex.Matches(item.Summary.Text,

“href\\s*=\\s*(?:\”(?<1>[^\”]*)\”|(?<1>\\S+))“, RegexOptions.None)

.Cast<Match>()

.Where(m =>

{

Uri url;

if (Uri.TryCreate(m.Groups[1].Value, UriKind.Absolute, out url))

{

string ext = Path.GetExtension(url.AbsolutePath).ToLower();

if (ext == “.png” || ext == “.jpg”) return true;

}

return false;

})

.Select(m => m.Groups[1].Value)

.FirstOrDefault();

}

}
} 

Añadiendo la imagen faltante.

La ruta que indicamos anteriormente proviene de la carpeta Assets, dentro de esta se encontrara la imagen que definimos previamente.

Para agregar susodicha imagen (Logito.jpg) solo hagamos click derecho sobre la carpeta Assets y seleccionemos la opción: Agregar: Elemento existente.

19

Seleccionamos la imagen y damos en Aceptar.

Nota//La imagen debe de contar con las siguientes medidas: Logito.jpg = 150×150 px.

Limpiemos y compilemos para comprobar que no tengamos ningún otro error.
Si no aparece ninguno, solo apretemos F5 y veamos el resultado.

20

Ya para que luzca un poco mejor cambiemos el nombre que aparece de “App1” por el de
Noticias Geeks”, vayamos al archivo App.xaml y localicemos la etiqueta que lo contiene.

21

Ctrl + Shift + B y después F5 para poder ver reflejado el cambio.

22

Si se selecciona cualquier noticia, así es como se muestra la descripción de la misma.

23

Ya con esto hemos terminado el desarrollo de nuestra primera aplicación para Windows 8, ahora lo que solo nos queda por realizar es darle un buen diseño, agregarle la barra de Charms en donde se exprese quien la desarrollo e información de contacto, la cual va dentro del “Acerca de” y estará listo para publicarse en la Store.

Para poder realizar esto último y si son estudiantes favor de mandar un correo a:

mstechsmart@hotmail.com

Bloque de Código Completo (/DataModel/SampleDataSource.cs)

/// <summary>
/// Crea una colección de grupos y elementos con contenido codificado de forma rígida.
///
/// SampleDataSource se inicializa con datos de marcadores de posición en lugar de con datos de producción
/// activos, por lo que se proporcionan datos de muestra tanto en el momento del diseño como en el de la ejecución.
/// </summary>

public sealed class SampleDataSource
{
public static readonly ObservableCollection<SampleDataGroup> AllGroups =
new ObservableCollection<SampleDataGroup>();
private static SampleDataSource _sampleDataSource = new SampleDataSource();
public static SampleDataGroup GetGroup(string uniqueId)
{

// La búsqueda lineal sencilla es aceptable para conjuntos de datos reducidos

var matches = AllGroups.Where((group) => group.UniqueId.Equals(uniqueId));

if (matches.Count() == 1) return matches.First();

return null;

}

public static SampleDataItem GetItem(string uniqueId)

{

// La búsqueda lineal sencilla es aceptable para conjuntos de datos reducidos

var matches = AllGroups.SelectMany(group => group.Items).Where((item) =>           item.UniqueId.Equals(uniqueId));

if (matches.Count() == 1) return matches.First();

return null;

}

public SampleDataSource()

{

}

public static async Task<bool> AddGroupForFeedAsync(string feedUrl)

{

if (SampleDataSource.GetGroup(feedUrl) != null) return false;

var feed = await new SyndicationClient().RetrieveFeedAsync(new Uri(feedUrl));

var feedGroup = new SampleDataGroup(

uniqueId: feedUrl,

title: feed.Title != null ? feed.Title.Text : null,

subtitle: feed.Subtitle != null ? feed.Subtitle.Text : null,

imagePath: feed.ImageUri != null ? feed.ImageUri.ToString() : “/Assets/Logito.jpg”,

description: null);
foreach (var i in feed.Items)

{

string imagePath = GetImageFromPostContents(i);

if (imagePath == null && feedGroup.Image != null)

imagePath = “/Assets/Logito.jpg”;

feedGroup.Items.Add(new SampleDataItem(

uniqueId: i.Id, title: i.Title.Text, subtitle: null, imagePath: imagePath,

description: null, content: Windows.Data.Html.HtmlUtilities.ConvertToText(i.Summary.Text), @group: feedGroup));

}

AllGroups.Add(feedGroup);
return true;

}
private static string GetImageFromPostContents(SyndicationItem item)
{
return Regex.Matches(item.Summary.Text,
“href\\s*=\\s*(?:\”(?<1>[^\”]*)\”|(?<1>\\S+))”,
RegexOptions.None)
.Cast<Match>()
.Where(m =>
{

Uri url;

if (Uri.TryCreate(m.Groups[1].Value, UriKind.Absolute, out url))
{
string ext = Path.GetExtension(url.AbsolutePath).ToLower();
if (ext == “.png” || ext == “.jpg”) return true;
}
return false;
})

.Select(m => m.Groups[1].Value)

.FirstOrDefault();
}
}
}

 

Hasta la proxima!!
Happy Coding!

Anuncios

4 comentarios sobre “Taller W8: Desarrollando mi primera App para Windows 8 con C#

Responder

Por favor, inicia sesión con uno de estos métodos para publicar tu comentario:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

w

Conectando a %s