Usar fuentes pesonalizadas en Apps Windows Phone y Windows Store

FontsIntroducción

La interfaz de usuario de las aplicaciones Windows Phone y Windows Store se basa en el uso del lenguaje Modern UI donde el correcto uso de fuentes obtiene un gran peso permitiendo otorgar un aspecto espaciado y ordenado facilitando el uso de la aplicación.

Segun las guías de estilo de ambas plataformas existen una serie de recomendaciones en cuanto al uso de fuentes que afectan al tipo de fuente, tamaño y espacio donde la fuente Segoe tiene un peso especial. Estas guías nos facilitan en muchas ocasiones el conseguir un aspecto adecuado con un correcto uso de las fuentes. Sin embargo, en ocasiones tenemos la necesidad de usar alguna fuente en concreto por diversos motivos:

  • La fuente en cuestión en base de la identidad corporativa de la aplicación que estamos desarrollando por lo que necesitamos usarla.
  • La fuente es ya usada en otros entornos como por ejemplo en aplicaciones para otros sistemas.
  • La fuente otorga un beneficio en la interfaz de usuario que queremos crear.

Sea por el motivo que sea, en ocasiones, nuestra aplicación tiene la necesidad de usar alguna fuente en concreto.

¿Cómo lo conseguimos?

Fuentes personalizadas

Tanto en el desarrollo de aplicaciones Windows Phone como en aplicaciones Windows Store tenemos acceso a una gran variedad de fuentes a las que podemos acceder utilizando la propiedad FontFamily en elementos de texto. Por defecto tenemos acceso a una gran variedad de fuentes:

  • Arial
  • Arial Black
  • Arial Unicode MS
  • Calibri
  • Cambria
  • Cambria Math
  • Comic Sans MS
  • Candara
  • Consolas
  • Constantia
  • Corbel
  • Courier New
  • Georgia
  • Lucida Sans Unicode
  • Segoe UI
  • Symbol
  • Tahoma
  • Times New Roman
  • Trebuchet MS
  • Verdana
  • Wingdings
  • Wingdings 2
  • Wingdings 3

Como podemos ver la variedad es alta pero… ¿y si la fuente que necesitamos utilizar no esta entre las fuentes disponibles?, ¿y si nuestra fuente (TTF) no se encuentra en el sistema?

¿Cómo usar fuentes personalizadas?

El trabajo con fuentes personalizadas en aplicaciones Windows Phone y Windows Store es sumamente sencillo. Comenzamos con el archivo o archivos de fuente en extesión .ttf. Para poder trabajar con las fuentes debemos tenerlas disponibles en nuestro proyecto.

NOTA: En este ejemplo vamos a utilizar la fuente Cheddar Jack disponible en el siguiente enlace.

Añadir la fuente a la solución

cheddar_jack

Cheddar Jack

Cheddar Jack

Incluimos el archivo TTF en una carpeta llamada Fonts dentro de los Assets de nuestra aplicación:

Añadimos las fuentes a nuestor proyecto

Añadimos las fuentes a nuestor proyecto

Tras añadir la fuente, en sus propiedades, estableceremos la propiedad Build Action a Content y la propiedad Copy to Output Directory a Copy if newer:

Content, Copy if never

Content, Copy if never

Para poder utilizar la fuente necesitamos además de saber la ruta y nombre del fichero, el nombre de la fuente (no es igual al nombre del fichero).

Obtener el nombre de la fuente

Para obtener el nombre de la fuente bastará con realizar doble clic sobre el fichero TTF:

Nombre de la fuente

Nombre de la fuente

En nuestro caso el nombre de la fuente es Cheddar Jack.

Utilizando la fuente

Añadimos un TextBlock en el contenido del Grid principal de nuestra aplicación y le añadimos en la propiedad FontFamily:

<TextBlock
     FontFamily="/Assets/Fonts/cheddar_jack.ttf#Cheddar Jack"
     FontSize="32"
     Text="Usando la fuente Cheddar Jack!" />

¿Qué significado tiene el texto que hemos indicado?

Ejemplo Fuentes 05

NOTA: Podemos renombrar el archivo TTF a por ejemplo CheddarJack.ttf y todo seguira funcionando correctamente. Sin embargo, la última parte, el nombre de la fuente, debe reflejar exactamente el nombre de la fuente incluidos espacios.

NOTA: Hay fuentes con problemas de compatibilidad. En estos casos si la fuente se llama Gothan Medium por ejemplo y tenemos problemas a la hora de acceder a la misma debemos quedarnos solo con la primera palabra, es decir, Gothan. Solo necesitamos realizar esta acción ante determinadas fuentes con problemas de compatibilidad.

Usando la fuente Cheddar Jack

Usando la fuente Cheddar Jack

Podéis descargar el ejemplo a continuación:

Extra

Ya hemos visto lo realmente sencillo que es trabajar con fuentes personalizadas en aplicaciones Windows Phone y Windows Store pero hay algunos detalles interesantes a comentar.

Acceso a la fuente en runtime

Podemos utilizar una fuente personalizada en runtime utilizando la propiedad FontFamily de un control de texto:

textBlock.FontFamily = new FontFamily("/Assets/Fonts/cheddar_jack.ttf#Cheddar Jack");

Trabajo organizado

Cuando toda nuestra aplicación accederá a fuentes personalizadas no debemos colocar la propiedad FontFamily continuamente con la ruta, nombre del fichero y nombre de la fuente. Debemos hacer un uso adecuado de la potencia disponible en XAML utilizando recursos y estilos.

Podemos crearnos un diccionario de recursos llamado Fonts. Dentro del archivo de recursos podremos organizar las fuentes de la siguiente forma:

<!-- Fonts -->
<FontFamily x:Key="LightFontFamily">/Fonts/Font-Light.ttf#Font Light</FontFamily>
<FontFamily x:Key="MediumFontFamily">/Fonts/Font-Medium.ttf#Font Medium</FontFamily>
<FontFamily x:Key="BlackFontFamily">/Fonts/Font-Black.ttf#Font Black</FontFamily>

Incluimos el diccionario de recursos entre los recursos de la aplicación:

<Application.Resources>
     <ResourceDictionary>
          <ResourceDictionary.MergedDictionaries>
               <ResourceDictionary Source="/Themes/Fonts.xaml"/>
          </ResourceDictionary.MergedDictionaries>
     </ResourceDictionary>
</Application.Resources>

Y desde cualquier control de texto bastara con:

<TextBlock
     FontFamily="{StaticResource LightFontFamily}"
     FontSize="32"
     Text="Usando la fuente Cheddar Jack!" />

Fácil y muy cómodo, ¿cierto?.

Más información

Anuncios

Unificación de las Stores de Windows y Windows Phone

Shopping BagIntroducción

Hasta el momento actual, como desarrolladores si nos interesaba crear Aplicaciones Windows Phone y Windows Store necesitábamos contar con dos cuentas de desarrollador, uno para cada plataforma. El coste de cada cuenta de desarrollador es el siguiente:

  • Usuario individual, 19$ para la Windows Phone Store y 49$ para la Windows Store.
  • Empresa, 19$ para la Windows Phone Store y 99$ para la Windows Store.

Además, contábamos con dos portales para cada Store. Hasta ahora…

¿Qué cambia exactamente?

Las Stores se unifican!. A partir de ahora como desarrolladores tendremos que realizar un único pago pudiendo publicar para ambas plataformas. El coste se queda de la siguiente forma:

  • Usuario individual: 19$ por las dos.
  • Empresa: 99$ por las dos.

Nos ahorramos dinero como desarrollador además de tener mayor facilidad al publicar Aplicaciones.

¿Y si…?

  • ¿Y si ya tenía cuenta de desarrollador de la Windows Store?

Ya tienes también cuenta de la Windows Phone Store.

  • ¿Y si ya tenía cuenta de desarrollador de la Windows Phone Store?

Ya tienes cuenta de la Windows Store.

  • ¿Y si tenía cuenta de ambas?

Pues Microsoft quiere premiar tu compromiso y te regalará un Token para poder renovar gratuitamente cuando caduque.

Más Información

[Windows 8.1] Introducción al control Hub

W8.1_LogoIntroducción

Recientemente se han presentado con grandes novedades para los desarrolladores .NET en el marco del //BUILD 2013. Se ha liberado Windows 8.1 y con el han llegado una gran variedad de novedades de cara a los desarrolladores. Entre las novedades recibidas tenemos un listado interesante de nuevos controles. El listado de nuevos controles es el siguiente:

  • AppBar controls
  • CommandBar
  • DatePicker
  • Flyout
  • Hub
  • Hyperlink
  • MenuFlyout
  • SettingsFlyout
  • TimePicker

De entre todos uno de los más interesantes ya que se utiliza como estructura base sobre la que crear la aplicación podemos destacar al control Hub.

El control Hub como ya hemos mencionado nos permite definir la estructura base de nuestra aplicación (tal y como nos lo permitía el control GridView por ejemplo). Nos permite estructuar la información en secciones donde lo más importante y atractivo visualmente se colocará a la izquierda mientras que el resto de opciones donde se profundiza más en la información se situa más a la derecha. El usuario accede a la información extra haciendo scroll horizontal. El objetivo del control es permitir mostrar la información con el mayor atractivo visual posible para atraer al usuario a descubrirla. Con respecto al GridView contamos con ventajas como:

  • No tenemos que enlazar al control a una colección de elementos. Podemos crear secciones con contenido y controles dispares en cada una de ellas.
  • Mayor capacidad de personalización.

Un ejemplo sencillo y reconocible de uso del control Hub lo podéis encontrar en la aplicación del tiempo:

El tiempo

El tiempo

Pinta bien, ¿te apuntas?

Arrancamos!

Abrimos Visual Studio 2013 Preview y creamos un nuevo proyecto. Dentro de la sección “Tienda Windows” contamos con las plantillas para crear aplicaciones Windows Store. Si nos fijamos contamos con novedades como por ejemplo la plantilla “Aplicación Hub” que nos crea la estructura de la aplicación utilizando el control Hub para ello. Podríamos utilizar la plantilla sin embargo para hacer el ejemplo lo más sencillo posible vamos a partir de una aplicación vacía:

Hub Template

Hub Template

Nos centramos en la vista principal (MainPage.xaml) donde vamos a añadir el control Hub. Partimos de lo más básico:

<Hub/>

No hay que agregar ni librerías ni namespaces. Recordar que es un nuevo control del SDK. Para desarrollar un poco el ejemplo vamos a simular la creación de una aplicación sobre la nueva Xbox. Continuamos estableciendo la propiedad básica, el título:

<Hub Header="Xbox One">
</Hub>

Fácil, ¿verdad?. El resultado hasta ahora sería algo asi:

Título del Hub

Título del Hub

El título en el control Hub siempre estará visible incluso cuando el usuario realice scroll horizontal sobre el contenido. El contenido del título puede ser tan simple como la cadena anterior o podemos requerir un contenido de mayor peso como imágenes o el botón volver por ejemplo. Podemos utilizar la propiedad Header para definir un contenido más complejo:

<Hub>
     <Hub.Header>
          <Grid>
          </Grid>
     </Hub.Header>
</Hub>

Añadiendo secciones

El control Hub se compone de secciones de tipo HubSection. El usuario accede a las secciones realizando scroll horizontal. En nuestro ejemplo sobre la Xbox One añadiremos tres secciones:

  • Primera sección: Mostrará una imágen sobre la consola junto a un titular.
  • Segunda sección: Descripción de la consola. Utilizaremos el control RichTextBox junto al nuevo control Hiperlink.
  • Tercera sección: Mostraremos el listado de juegos en el ya conocido control GridView.

Suena bien, ¿cierto?. Manos a la obra!

Vamos a definir la estructura base de secciones que sería algo como lo siguiente:

<Hub Header="Xbox One">
     <HubSection>
     </HubSection>
     <HubSection Header="Qué es" Width="500">
     </HubSection>
     <HubSection Header="Juegos" Width="1200">
     </HubSection>
</Hub>

El resultado:

Ya tenemos secciones.

Ya tenemos secciones.

Nos centramos en la primera sección. Ya hemos comentado que vamos a añadir un banner que cubra una zona importante para llamar la atención del usuario junto a un titular. Dado que queremos cubrir toda la zona de la sección con la imágen la estableceremos como fondo:

<HubSection Width="800">
     <HubSection.Background>
          <ImageBrush ImageSource="/Assets/Xbox.jpg" Stretch="UniformToFill"/>
     </HubSection.Background>
</HubSection>
Vamos mejorando

Vamos mejorando

Y el titular, simple, ¿o no?. Las secciones del control Hub soportan cualquier tipo de contenido, desde un simple botón a un complejo GridView sin embargo no tienen ninguna propiedad Content. Estableceremos el contenido estableciendo su DataTemplate:

<DataTemplate>
     <RichTextBlock>
          <Paragraph FontSize="32">
          Te damos la bienvenida a una nueva generación!
          </Paragraph>
     </RichTextBlock>
</DataTemplate>

Pasamos a la segunda sección. En esta sección vamos a añadir información sobre la consola. Vamos a utilizar para ello el control RichTextBox:

<DataTemplate>
     <RichTextBlock>
          <Paragraph FontSize="20">
          Te damos la bienvenida a una nueva generación de juegos y entretenimiento. En la que los juegos superan las barreras del realismo. Y puedes escuchar música mientras juegas. Donde puedes pasar de ver la TV a películas, música y juegos en un instante. Y vivir una experiencia totalmente personalizada. Donde todo lo que te entretiene está en un solo lugar. Esto es Xbox One, el sistema que lo incluye todo.
          </Paragraph>
          <Paragraph FontSize="20">
          Xbox One es una modernísima consola de juegos, una TV de última generación, un centro de cine en casa y muchísimo más. Los días en los que tenías que cambiar los enchufes de la TV para jugar o ver una película han pasado a la historia. Con Xbox One, puedes pasar rápidamente de la TV a películas, música o juegos. Solo necesitas tu voz para hacerlo.
          </Paragraph>
     </RichTextBlock>
</DataTemplate>

Otro de los controles añadidos en Windows 8.1 es el control Hyperlink. Nos permite definir enlaces dentro del texto enriquecido. La interpretación del texto es exactamente igual al resto con la única diferencia de ser marcado con un color diferente y por supuesto que al ser pulsado nos redirige a una URI especificada.

Añadimos al RichTextBox un enlace:

<Hyperlink FontSize="28" Foreground="DarkGreen" NavigateUri="http://www.xbox.com/es-ES/xboxone/meet-xbox-one">Sorpréndete.</Hyperlink>

La propiedad fundamental del control Hyperlink es NavigateUri donde especificamos la URI a donde se navegará al pulsar el enlace.

El resultado hasta ahora:

Segunda sección preparada

Segunda sección preparada

Vamos a por la tercera sección. En esta sección vamos a añadir un control de mayor peso añadiendo un GridView donde mostrar el listado de juegos de la consola.

Creamos una carpeta “Models” donde definiremos la clase Games donde almacenaremos la información de cada juego:

public class Game
{
     public string Title { get; set; }
     public string Description { get; set; }
     public string Image { get; set; }
}

A continuación, creamos una carpeta “ViewModels” donde prepararemos la colección de juegos que se mostrará en la vista:

public class MainViewModel
{

     public List<Game> Games
     {
          get;
          set;
     }

     public MainViewModel()
     {
          Games = new List<Game>();
          Games.Add(new Game { Title = "Forza Motorsport 5", Description = "Forza Motorsport, la franquicia de carreras mejor valorada de la última década, vuelve con una experiencia de conducción total de última generación creada en exclusiva para Xbox One.", Image = "http://compass.xboxlive.com/assets/cb/19/cb19177d-969a-48dc-91f2-d6e8416968d6.jpg?n=XBR_Game1.jpg" });
          Games.Add(new Game { Title = "Ryse", Description = "En medio del caos de la última etapa del Imperio Romano, conviértete en el soldado Marius Titus y súmate a una trepidante campaña para vengar la muerte de tu familia.", Image = "http://compass.xboxlive.com/assets/69/d2/69d2d734-7a15-40b5-a7b9-9baea1937c40.jpg?n=XBR_Game4.jpg" });
          Games.Add(new Game { Title = "Dead Rising 3", Description = "Todo vale como arma en Dead Rising 3. Explora la ciudad de Los Perdidos (California) como Nick Ramos, un mecánico con un pasado misterioso, que debe encontrar el modo de escapar antes de que un ataque militar acabe con la ciudad y todos sus habitantes.", Image = "http://compass.xboxlive.com/assets/83/c7/83c74b66-5f24-4263-bc03-3c3c021c4a11.jpg?n=XBR_Game5.jpg" });
          Games.Add(new Game { Title = "Call of Duty: Ghosts", Description = "La franquicia que ha sentado las bases de toda una generación de juegos se pone el listón aún más alto con el nuevo Call of Duty: Ghosts.", Image = "http://compass.xboxlive.com/assets/07/bb/07bbfdcf-646b-4ac9-b764-c8253e7dabc3.jpg?n=XBR_Game3.jpg" });
          Games.Add(new Game { Title = "Quatum Break", Description = "Domina el tiempo para sobrevivir al presente… y salva el futuro. De los creadores de Alan Wake y Max Payne llega Quantum Break, una experiencia de entretenimiento revolucionaria a medio camino entre el juego y la televisión.", Image = "http://compass.xboxlive.com/assets/aa/84/aa842d82-5c4e-4292-a12c-432af66f1e53.jpg?n=XBR_Game2.jpg" });
     }
}

En el code behind de la vista principal (MainPage.xaml.cs) establecemos el DataContext al ViewModel creado:

DataContext = this.DataContext ?? new MainViewModel();

Ya tenemos la infraestructura necesaria para definir nuestro listado de juegos, pasamos a la vista. Definimos un GridView:

<HubSection Header="Juegos" Width="1200">
     <DataTemplate>
          <GridView>
          </GridView>
     </DataTemplate>
</HubSection>

Hacemos Binding a la colección de juegos:

<HubSection Header="Juegos" Width="1200">
     <DataTemplate>
          <GridView SelectionMode="None"
          ItemsSource="{Binding Games}">
          </GridView>
     </DataTemplate>
</HubSection>

Establecemos el DataTemplate con la defnición de como se verá cada juego en la lista y como están organizados:

<HubSection Header="Juegos" Width="1200">
     <DataTemplate>
          <GridView SelectionMode="None" ItemTemplate="{StaticResource Standard310x260ItemTemplate}"
          ItemsSource="{Binding Games}">
               <GridView.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapGrid Orientation="Horizontal"/>
                    </ItemsPanelTemplate>
               </GridView.ItemsPanel>
          </GridView>
     </DataTemplate>
</HubSection

Si ejecutamos obtendremos el siguiente resultado:

GridView como sección del Hub

GridView como sección del Hub

NOTA: Al GridView de la sección no se puede acceder desde el code behind aun asignándole un nombre.

IsHeaderInteractive=”True”

Lo visto hasta ahora del control es muy interesante pero sería insuficiente para poder gestionar toda la lógica necesaria en una aplicación real. En nuestro ejemplo sobre la nueva Xbox One mostramos un listado de juegos. Lo ideal sería mostrar el listado de juegos top, los más recientes o lo más destacados por ejemplo y al pulsar sobre la cabecera, mostrar una vista de detalles con el listado completo de juegos.

Efectivamente os sonará esta posibilidad a la ya utilizada en el control GridView por ejemplo.

¿Es posible realizarlo?

Claro!. Las secciones del control Hub cuentan con una propiedad para activar esta posibilidad llamada isHeaderInteractive:

<HubSection Header="Juegos" Width="1200" IsHeaderInteractive="True"/>

Ahora debemos añadir el evento clic que se produce al pulsar las cabeceras:

<Hub Header="Xbox One" SectionHeaderClick="Hub_SectionHeaderClick" />

Por último, en el controlador del evento clic podemos determinar con facilidad la cabecera pulsada gracias al EventArgs del evento:

private void Hub_SectionHeaderClick(object sender, HubSectionHeaderClickEventArgs e)
{
     if(e.Section.Name == "Juegos")
     {
          //Navegamos a la vista de detalles!
     }
}

Podéis ver el resultado del ejemplo en el siguiente video:

También podéis descargar el código fuente del ejemplo desde el siguiente enlace:

Espero que lo visto en la entrada os sea de interés. Recordar que si os surgen dudas o sugerencias podéis dejarlas en los comentarios de la entrada.

Keep Pushing!

Más información

Novedades de Windows 8.1

Introducción

Recientemente se han presentado grandes novedades para los desarrolladores .NET en el marco del //BUILD 2013. Se ha liberado Windows 8.1 Preview junto a Visual Studio 2013 Preview. Podéis descargar Windows 8.1 Preview desde http://preview.windows.com y Visual Studio 2013 Preview desde la página de descargas del Dev Center.

Windows 8.1 Preview

Windows 8.1 Preview

Windows 8.1. Novedades como sistema

La vuelta del botón inicio

Se rumoreaba desde hace tiempo con capturas filtradas y múltiples suposiciones. Algunos usuarios no se encontraban agusto sin el botón inicio. Ha vuelto. Pero esperad, no es el botón inicio tradicional que conocéis, si lo pulsamos nos guía a la interfaz Modern UI. Si hacemos clic derecho nos aparecerá un popup con acceso rápido a múltiples opciones desde acceder a la interfaz Modern UI a apagar el sistema.

Vuelve el botón inicio!

Vuelve el botón inicio!

También ha sido atendida otra petición pública bastante extendida que pedía el poder acceder directamente al escritorio clásico sin pasar por la interfaz Modern UI.

Nuevos tiles!

Contamos con dos nuevos tamaños para tiles permitiendos una mayor libertad a la hora de gestionar nuestro escritorio Modern UI.

Nuevos Tiles

Nuevos Tiles

Multitarea mejorada

Si en Windows 8 una de las características más interesantes era la multitarea y la posibilidad de tener dos aplicaciones de manera simultánea. En Windows 8.1 podemos tener hasta cuatro aplicaciones a la vez pudiendo además marcar el tamaño elegido para cada una de ellas.

NOTA: Al igual que en Windows 8 se deben de cumplir unos requisitos mínimos de resolución.

Búsquedas más potentes

En la barra de charms seguimos contando con la posibilidad de realizar de manera rápida búsquedas en el sistema y las aplicaciones. Ahora se añaden integración con archivos skydrive, el disco duro o las aplicaciones integradas en el sistema en una nueva interfaz (impresionante) que nos permite realizar acciones directas con rapidez como reproducir un video o un audio directamente.

Búsquedas

Búsquedas

Nueva tienda

Se ha rediseñado el aspecto de la tienda en una búsqueda de mayor usabilidad permitiendo encontrar o descubrir con más rapidez lo buscado. La novedad más atractiva en este punto son las actualizaciones automáticas de las aplicaciones.

Otros cambios

  • Soporte nativo para impresoras 3D.
  • LockScreen mucho más versátil.
  • Mejoras en Xbox Music.
  • Nuevas aplicaciones!
  • Más idiomas soportados (139!).
  • Etc.

En definitiva se han reforzado todas las partes importantes del sistema atendiendo también a las peticiones más importantes del público. Podéis ver un resúmen de las novedades en el siguiente video:

Lo que nos interesa, novedades en el desarrollo!

Mejoras en os Live Tiles

Los Tiles (baldosas) son uno de los pilares fundamentales de la atractiva interfaz de usuario que tenemos disponible en Windows 8.

En Windows8.1 nos ofrecerán una mayor flexibilidad y oportunidades en nuestras aplicaciones. Ahora podremos definir el live tile en el archivo de manifiesto de modo que comenzará a actualizarse de inmediato sin la necesidad de que el usuario abra e interaccione con la Aplicación.

Además, contamos con nuevos tamaños:

  • Small Tiles: 70x70px
  • Large Tiles: 310x310px
Nuevos Tiles!

Nuevos Tiles!

Recordar que en Windows 8 ya contábamos con dos tamaños de tiles:

  • Square Tiles: 150x150px
  • Wide Tiles: 310x150px

Por lo tanto ahora contamos con hasta 4 tipos diferentes de tiles. Para facilitar su identificación han sido renombrados:

  • Small = Square 70x70px
  • Medium = Square 150x150px
  • Wide = Wide 310x150px
  • Large = Square 310x310px

NOTA: Por compatibilidad los nombres antiguos siguen siendo válidos aunque se recomienda utilizar los nuevos.

Nuevos Controles!

Se han añadido mútiples controles nuevos tanto para XAML como para WinJS:

En XAML contamos con:

AppBar. En Windows 8.1 contamos un nuevos controles que nos permiten crear botones para el ApplicationBar que reflejen y respeten las guías de diseño y comportamiento establecidas sin grandes esfuerzos por parte de los desarrolladores. Contamos con tres tipos diferententes de controles:

Las diferencias con respecto a botones normales serían:

  • Por defecto son circulares en lugar de rectangulares.
  • Su contenido se establece con las propiedades Label e Icon en lugar de la propiedad Content.

El ejemplo básico de un AppBarButton sería:

<AppBarButton Icon="Test" Label="Example" Click="AppBarButton_Click"/>

Mientras que un AppBarToggleButton se definiría asi:

<AppBarToggleButton Label="Example" Click="AppBarButton_Click">
    <AppBarToggleButton.Icon>
        <PathIcon Data="F1 M 20,20L 24,10L 24,24L 5,24"/>
    </AppBarToggleButton.Icon>
</AppBarToggleButton>

Por último, un separador visual entre los botones, es decir, el AppBarSeparator se define:

<AppBarSeparator />

CommandBar. Este control nos facilita la creación de ApplicationBar en nuestras aplicaciones. El control nos proporciona:

  • Layout adecuados con botones principales alineados a la izquierda y los botones secundarios alineados a la derecha.
  • Autoescala los botones para adaptarse a cambios de resolución o de orientación.
<Page.BottomAppBar>
    <CommandBar>
        <AppBarButton Icon="Back" Label="Back" Click="AppBarButton_Click"/>
        <AppBarButton Icon="Stop" Label="Stop" Click="AppBarButton_Click"/>
        <AppBarButton Icon="Play" Label="Play" Click="AppBarButton_Click"/>
        <AppBarButton Icon="Forward" Label="Forward" Click="AppBarButton_Click"/>
        <AppBarSeparator/>
        <AppBarToggleButton Icon="Shuffle" Label="Shuffle" Click="AppBarButton_Click"/>
        <AppBarToggleButton Icon="RepeatAll" Label="Repeat" Click="AppBarButton_Click"/>
        <CommandBar.SecondaryCommands>
            <AppBarButton Icon="Like" Label="Like" Click="AppBarButton_Click"/>
            <AppBarButton Icon="Dislike" Label="Dislike" Click="AppBarButton_Click"/>
        </CommandBar.SecondaryCommands>
    </CommandBar>
</Page.BottomAppBar>

DatePicker.  Lo habíais echado de menos, ¿verdad?. Nuevo control destinado a capturar fechas en tus aplicaciones.

DatePicker

DatePicker

Diseñado para funcionar con teclado y ratón además de por supuesto táctil. Su uso muy simple:

<DatePicker x:Name=myDatePicker Header="Introduzca la fecha:"/>

Podemos establecer la fecha (propiedad Date) desde código o haciendo Binding a una instancia de tipo DateTimeOffset.

Por supuesto el control es altamente personalizable utilizando estilos y plantillas y soporta los layouts horizontales y verticales.

Flyout. Control destinado a mostrar en un popup temporal contenido adicional relacionado con la acción realizada por el usuario.

Flyout

Flyout

Hub. Destinado a reproducir con facilidad el patrón de diseño Hub ya visible en múltiples aplicaciones. El control Hub como ya hemos mencionado nos permite definir la estructura base de nuestra aplicación (tal y como nos lo permitía el control GridView por ejemplo). Nos permite estructuar la información en secciones donde lo más importante y atractivo visualmente se colocará a la izquierda mientras que el resto de opciones donde se profundiza más en la información se situa más a la derecha. El usuario accede a la información extra haciendo scroll horizontal. El objetivo del control es permitir mostrar la información con el mayor atractivo visual posible para atraer al usuario a descubrirla.

<Hub Header="News">
    <HubSection MinWidth="600" Header="Latest">
        <DataTemplate>
            <Grid>
            </Grid>
        </DataTemplate>
    </HubSection>

    <HubSection Header="Tech" IsHeaderInteractive="True" MinWidth="250">
        <DataTemplate>
            <StackPanel>

            </StackPanel>
        </DataTemplate>
    </HubSection>

    <HubSection Header="Sports" IsHeaderInteractive="True" MinWidth="250">
        <DataTemplate>
            <StackPanel>

            </StackPanel>
        </DataTemplate>
    </HubSection>
</Hub>
Hub

Hub

Hyperlink. Control que nos permite añadir enlaces. El tratamiento que recibe es exactamente igual al resto del texto. La diferencia se aplica asignándole un color diferente y que al ser pulsado navega a una URI. Su uso sencillo:

<RichTextBlock Width="200" Style="{StaticResource BasicRichTextStyle}">
    <Paragraph>Hyperlinks let you give readers a visual hint that certain text links to other content.
        <Hyperlink NavigateUri="http://dev.windows.com">Read more on the Windows Dev Center</Hyperlink>
        ... Text in a Hyperlink element is treated like the rest of the text and participates in line breaking.
    </Paragraph>
</RichTextBlock>
Hyperlink

Hyperlink

MenuFlyout. Control que nos pemite mostrar un popup temporal con un listado de opciones. Lo utilizaremos para que el usuario pueda elegir una opción entre varias opciones. Se oculta cuando el usuario pulsa sobre una opción o al pulsar fuera del control.

<Button Content="Options">
    <Button.Flyout>
        <MenuFlyout>
            <MenuFlyoutItem Text="Reset"/>
            <MenuFlyoutSeparator/>
            <ToggleMenuFlyoutItem Text="Shuffle" IsChecked="{Binding IsShuffleEnabled, Mode=TwoWay}"/>
            <ToggleMenuFlyoutItem Text="Repeat" IsChecked="{Binding IsRepeatEnabled, Mode=TwoWay}"/>
        </MenuFlyout>
    </Button.Flyout>
</Button>
MenuFlyout

MenuFlyout

SettingsFlyout. Control que nos permite crear flyouts de configuración de manera fácil respetando todos los puntos de las guías de estilo.

SettingsFlyout

SettingsFlyout

TimePicker. Control que nos permite capturar tiempos en nuestras aplicaciones. Diseñado para funcionar con teclado y ratón además de por supuesto táctil. Su uso muy simple:

<TimePicker x:Name=myTimePicker Header="Insert Time"/>
TimePicker

TimePicker

En WinJS también tenemos un listado de nuevos controles:

Otras novedades

Entre una lista considerable de cambios en la API podemos destacar:

  • Cambios en la gestión de temas. En Windows 8 el tema de la aplicación se establecía una vez en arranque y no se podia cambiar dinámicamente o establecerlo a zonas concretas (controles determinados por ejemplo). En Windows 8.1 podemos hacer ambas cosas.
  • Nueva API Scheduler. Nos permite definir la prioridad de los tasks pudiendo desarrollar aplicaciones más adaptadas eficientemente a los recursos del sistema.
  • Nueva API Http Client (HTTP y REST).
  • Mejoras múltiples de rendimiento (mejorado hasta en un 40% Bindings).
  • Mejoras en el sistema de bindings (TargetNullValue, Fallback Value, etc).

En definitiva,  más de 650 nuevas APIs disponibles en Windows 8.1!. ¿No os entran ganas de “hincarle” el diente?. En próximas entradas iremos analizando las posibilidades que nos brindan los nuevos controles asi como las nuevas APIs disponibles.

Keep Pushing!

Más información

[Evento CartujaDotNet] Wave Engine. Desarrollo de videojuegos multiplataforma!

El evento

El desarrollo de aplicaciones para dispositivos móviles es un área que gana adeptos y suma peso día a día. Entre las aplicaciones destacadas, más descargadas y que aportan grandes beneficios contamos con los juegos. Dada la variedad de dispositivos, SDKs, herramientas y lenguajes a aprender, sacar el máximo partido a cada plataforma con eficacia y rapidez es una tarea complicada.  Wave Engine es un motor multiplataforma en 3D para facilitar la adaptación de los juegos móviles a cualquier plataforma (Android, iOS, Windows Phone y Windows 8). Incluye multitud de herramientas que facilitan tareas importantes como la gestión de publicidad, analítica del juego, etc.

En este evento se realizará una introducción al engine donde se mostrarán todas sus  posibilidades.

WaveEngine

Fecha

El evento tendrá lugar el próximo Jueves, 23 de Mayo de 19:30h a 21:30h (2 horas de duración).

Lugar

Tendrá lugar en el Cloud Pointing de Sevilla situado en el Parque Empresarial Nuevo Torneo. Tenéis la información exacta del lugar a continuación:

c\ Biología, 12, Edificio Vilamar 2, 3ª Planta
Parque Empresarial Nuevo Torneo
41015 Sevilla

Ponentes

  • Marcos Cobeña (LIGHTYEAR): Developer Advisor en Plain Concepts.
  • David Ávila (WOODY): Software Developer Advisor Plain Concepts.

Más información

¿Te lo vas a perder?

Resumen Megathon Sevilla 2013

Introducción

Los pasados días 12, 13 y 14 de Abril se ha celebrado en Sevilla el Megathon Windows 2013, concurso que celebrado de manera simultánea en varias ciudades.

Megathon Windows 2013

Megathon Windows 2013

El lugar

El evento tenía lugar en el Cloud Pointing de Sevilla situado en el Parque Empresarial Nuevo Torneo. La sala en la que nos situabamos estaba bastante bien equipada con proyectores, buena disposición de mesas, aire acondicionado, etc. Además la zona era de fácil acceso y con bastante aparcamiento. Sin duda un lugar interesante para realizar eventos de esta índole. Agradecer la colaboración de Marcos Bueno y de Guillermo por su colaboración y hacer que todo sea tán fácil.

Los Coordinadores / Mentores

Los mentores del evento eramos:

  • Javier Suárez Ruiz. Trabajo como Arquitecto de Software en Icinetic en tecnologías y arquitecturas .NET. (@jsuarezruiz)
  • Marcos Cobeña Trabaja como Developer Advisor en PlainConcepts, en el grupo @WaveEngineTeam (@cobenaMarcos)

Las Aplicaciones presentadas

  • Autobuses: Aplicación para Windows 8 realizada utilizando XAML + C# basada en el uso de mapas para indicar las diferentes rutas de autobuses en Sevilla:
Autobuses Sevilla

Autobuses Sevilla

  • Animales Perdidos: Aplicación para Windows Phone 8 que permite poder anunciar la pérdida de animales y facilita de esta forma también su recuperación. El backend estaba en SQL Server al que se accedía mediante servicios WCF:
Animales Perdidos

Animales Perdidos

  • Chuck Norris Facts: Aplicación Windows 8 con frases míticas de Chuck Norris. Muy buen uso de Text to Speech:
Chuck Norris Facts

Chuck Norris Facts

  • Pick a Gem: Juego para Windows 8 realizado con WinJs. Meritorio port realizado por una única persona de un juego realizado con CreateJs:
Pick a Gem

Pick a Gem

  • YarrReader: Lector de noticias integrado con SkyDrive para gestionar la información en la nube. La intención de los componentes del grupo es realizar la aplicación tanto para Windows 8 como para Windows Phone 8. Para ello, la estructura del proyecto hace uso de Portable Class Library entre otras características destacables:
Reader

YarrReader

  • Ready Steady Shoot!: Juego de disparos ambientado en el Oeste para Windows 8 realizado utilizando XAML + C#. Idea facilitada por mi compañero Marcos Cobeña que el grupo formado por dos personas llevo a cabo con gran acierto:
Shoot

Ready Steady Shoot!

  • Twistballs: Juego para Windows 8 realizado con XAML con un gran uso del motor de físicas basado en Farseer (Ganadores del Concurso):
TwistBalls

TwistBalls

  • Machacalo: Juego de habilidad para Windows Phone 8 realizado con XAML y C#:
Machacalo

Machacalo

  • Bullealos: Interesante aplicación social para Windows 8 realizada en XAML + C# con un sólido backendo haciendo uso de Azure en todo su esplendor:
Bullealos

Bullealos

Los ganadores

Y finalmente tras una reñida y divertida votación realizada por el público los ganadores han sido:

TwistBalls

TwistBalls

El grupo ganador estaba formado por los siguientes integrantes:

Gran juego desarrollado para Windows 8 con XAML y C# apoyandose en el motor de físicas farseer. Sin duda una apuesta muy sólida, bien diseñada y lo más importante muy divertida.

Harlem Shake

El Viernes los chicos de Nokia Spain lanzaron un nuevo reto a todas las ciudades del Megathon. La ciudad que realizara el mejor Harlem Shake ganaría un Nokia Lumia 520 por cada participante. Sin duda desde el sábado los chicos venían preparados:

Como en casa...

Como en casa…

Y el resultado final…

Conclusiones

Las sensaciones que personalmente tengo del evento son inmejorables. Gente con ilusión y ganas desarrollando sin parar, espíritu de colaboración, muy animados todos. Como coordinador no puedo más que agradecer a los chicos del Cloud Pointing, a Marcos Cobeña por su inestimable ayuda, a Jose Bonnin junto a su equipo por todo el esfuerzo y ayuda prestada y por supuesto a todos los asistentes. Espero que sin duda se hayan divertido tanto como yo. Un placer haber podido ayudar en lo posible. Recordar a todos los grupos que pueden contar conmigo para terminar las apps, todos tienen opciones en los premios nacionales.

Para cerrar sólo me queda dejar en el aire para quien quiera recogerlo…

¿Repetimos?

I APP YOU!

El concurso

Microsoft Ibérica inaugura un interesante concurso semanal. Desde el 1 de Febrero al 15 de Mayo se sorteará una Xbox 360 entre todas las aplicaciones publicadas en la Windows Phne Store. Además, se sorteará otra Xbox 360 entre todos los desarrolladores que publiquen una aplicación entre las fechas mencionadas en la Windows Store.

Además, si para el desarrollo de las aplicaciones activáis una subscripción a Windows Azure podéis ganar una subscripción a MSDN.

Los premios se adjudican por sorteo. Es decir, no hay jurado, sólo la suerte os acompaña. Sin embargo, recordar que no hay mayor premio que aportar una gran aplicación de calidad, aprender y disfrutar realizandola. Evitad “inundar” las Stores con clones sin valor buscando únicamente el premio material (Xbox 360).

¿Os animáis?

I APP YOU

I APP YOU

Más información

[Evento] Vuelven los “Pelochos”. Técnicas para compartir código.

El evento

El próximo Martes 29 de Enero estaré junto a los chicos de Second Nug retomamos la segunda parte del evento sobre Windows 8 y Windows Phone 8.

Aprenderemos las compatibilidades entre WP7 y WP8, compartiremos código entre Windows Phone (7 y 8) y Windows 8, todo esto a punta de Visual Studio. Analizaremos las técnicas actuales usadas para estos fines, desde CTRL+C y CTRL+V hasta las Portable Class Libray incluyendo buenas prácticas a nivel de interfaz de usuario.

Si quieres saber que cantidad de código podemos compartir entre aplicaciones Windows Phone y Windows 8 o cual es el equivalente al GridView con Zoom semántico de Windows 8 en Windows Phone 8, no te pierdas el evento. Puedes registrarte ya desde aquí.

Vuelven los "Pelochos"

Vuelven los “Pelochos”

Más información

Windows 8. Selector de archivos (FilePicker).

FilePicker

En ocasiones desde nuestras aplicaciones Windows Store necesitaremos realizar acciones como:

  • Acceder a un archivo.
  • Guardar una localización.
  • Acceder a una carpeta.

En estas ocasiones vamos a integrar el contrato del selector de archivos (FilePicker). A través del selector de archivos, nuestras aplicaciones puede obtener acceso a archivos y carpetas del sistema.

Una vez que el usuario selecciona archivos o carpetas, la aplicación recibe estas selecciones como objetos StorageFile y StorageFolder.

Package.Appxmanifest

Como siempre solemos hacer vamos a realizar un ejemplo lo más simple posible pero que nos sea válido para lograr nuestros objetivos. La plantilla selecciona para realizar el ejemplo lo más simple posible será “Blank Application”:

Blank Application

Al igual que en el resto de contratos que nos permiten interactuar con el sistema, es necesario modificar el archivo package.appxmanifest. Comenzamos por ello:

Package.Appxmanifest

Package.Appxmanifest

Dado que en nuestro ejemplo vamos a abrir (leer) archivos como guardarlos, añadimos ambas declaraciones en el archivo de manifiesto.

Manos a la obra

Comenzamos creando la interfaz de usuario de nuestra aplicación. Deseamos probar las posibilidades del contrato del selector de archivos. Vamos a crear cuatro botones que nos permitirán:

  • Seleccionar un archivo.
  • Seleccionar múltiples archivos.
  • Seleccionar una carpeta.
  • Guardar un fichero.
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
     <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
          <Button x:Name="btnSelectSingleFile" Width="300" Height="150" Content="Seleccionar archivo"/>
          <Button x:Name="btnSelectMultipleFile" Width="300" Height="150" Content="Seleccionar múltiples archivos"/>
          <Button x:Name="btnSelectFolder" Width="300" Height="150" Content="Seleccionar una carpeta"/>
          <Button x:Name="btnSaveFile" Width="300" Height="150" Content="Guardar un archivo"/>
     </StackPanel>
</Grid>

Añadimos los eventos Click de cada botón:

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
     <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
          <Button x:Name="btnSelectSingleFile" Width="300" Height="150" Content="Seleccionar archivo" Click="btnSelectSingleFile_Click"/>
          <Button x:Name="btnSelectMultipleFile" Width="300" Height="150" Content="Seleccionar múltiples archivos" Click="btnSelectMultipleFile_Click"/>
          <Button x:Name="btnSelectFolder" Width="300" Height="150" Content="Seleccionar una carpeta" Click="btnSelectFolder_Click"/>
          <Button x:Name="btnSaveFile" Width="300" Height="150" Content="Guardar un archivo" Click="btnSaveFile_Click"/>
     </StackPanel>
</Grid>

En el code-behind:

private void btnSelectSingleFile_Click(object sender, RoutedEventArgs e)
{

}

private void btnSelectMultipleFile_Click(object sender, RoutedEventArgs e)
{

}

private void btnSelectFolder_Click(object sender, RoutedEventArgs e)
{

}

private void btnSaveFile_Click(object sender, RoutedEventArgs e)
{

}

Si compilamos veremos el siguiente resultado:

FilePicker 1

Obtener un fichero

Comenzamos por el caso más simple, seleccionar un archivo del disco duro del usuario. Nos centramos en el evento Click del primero botón. Creamos un objeto de tipo FileOpenPicker. Este objeto será el encargado de abrir el selector de archivos que se mostrará al usuario donde podrá seleccionar un archivo que podrá retornar a nuestra aplicación.

Tenemos que indicar el tipo de ficheros a abrir mediante fileTypeFilter. Este punto es obligatorio, no estamos autorizados a ignorar el filtro o establecer un comodín (*). Debemos establecer al menos un tipo de filtro.

Por último, recordar que el objetivo es conseguir un archivo. Una vez que el usuario seleccione un archivo se devolverá a nuestra aplicación el archivo como un StorageFile:

private async void btnSelectSingleFile_Click(object sender, RoutedEventArgs e)
{
     FileOpenPicker picker = new FileOpenPicker();
     picker.FileTypeFilter.Add(".png");
     StorageFile file = await picker.PickSingleFileAsync();
}

Para obtener un archivo llamaremos al método asíncrono PickSingleFileAsync.

La interfaz que visualizará el usuario será la siguiente:

FilePicker 2

Obtener Múltiples ficheros

En ocasiones necesitaremos obtener más de un archivo. En esta ocasión utilizaremos el método pickMultipleFilesAsync() del objeto FileOpenPicker:

private async void btnSelectMultipleFile_Click(object sender, RoutedEventArgs e)
{
     FileOpenPicker picker = new FileOpenPicker();
     picker.FileTypeFilter.Add(".png");
     picker.FileTypeFilter.Add(".jpg");

     picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
     picker.ViewMode = PickerViewMode.Thumbnail;
     IReadOnlyList<StorageFile> files = await picker.PickMultipleFilesAsync();
}

Pocas diferencias con respecto al ejemplo anterior. El único cambio significativo es que una vez que el usuario selecciona los ficheros elegidos, en nuestra aplicación obtendremos una colección de objetos StorageFile.

FilePicker 3

Seleccionar una carpeta

Una opción interesante y muy común a realizar en nuestras aplicaciones es la selección de una carpeta en lugar de un fichero. Permitir al usuario elegir una ubicación para utilizar en el futuro o seleccionar el lugar donde se guardarán archivos son opciones donde nos interesará utilizar el contrato de selección de archivos para seleccionar una carpeta.

Una opción muy interesante que se nos ofrece es que una vez seleccionada una carpeta podemos guardarla como carpeta por defecto para nuestra aplicación. Se nos conceden derechos de lectura y escritura para dicha carpeta en el futuro sin solicitar permisos constantemente al usuario.

private async void btnSelectFolder_Click(object sender, RoutedEventArgs e)
{
     FolderPicker folderPicker = new FolderPicker();
     folderPicker.FileTypeFilter.Add(".png");
     StorageFolder folder = await folderPicker.PickSingleFolderAsync();
     if (folder != null)
     {
          StorageApplicationPermissions.FutureAccessList.AddOrReplace("DefaultFolder", folder);
     }
}

Como se puede observar en el código superior todo el código ya es familiar. Utilizamos un objeto de tipo FolderPicker. Si se devuelve una carpeta a nuestra aplicación podemos establecerla como carpeta por defecto mediante StorageApplicationPermissions.FutureAccessList. De esta manera, evitamos pedir constantemente permisos al usuario para realizar operaciones en dicha carpeta.

FilePicker 4

Guardar un fichero

En ocasiones nos interesará guardar un fichero en la máquina del usuario. Tenga en cuenta que podemos guardar el fichero en carpetas comunes del sistema. Si la aplicación se desinstala, el fichero puede permanecer e incluso puede llegar a ser utilizado por otras aplicaciones. Si se desea guardar un fichero en el almacenamiento asilado de la aplicación se debe utilizar otros métodos.

La gran diferencia con los casos anteriores donde seleccionabamos archivos será el objeto a utilizar. En lugar de utilizar un archivo FileOpenPicker, utilizaremos un objeto de tipo FileSavePicker:

private async void btnSaveFile_Click(object sender, RoutedEventArgs e)
{
     FileSavePicker savePicker = new FileSavePicker();
     savePicker.SuggestedStartLocation = PickerLocationId.Downloads;
     savePicker.FileTypeChoices.Add("Image", new List<string>() { ".png", ".jpg", ".bmp" });
     savePicker.SuggestedFileName = "Imagen";
     StorageFile file = await savePicker.PickSaveFileAsync();
}

De manera similar a cuando añadíamos filtros al objeto FileOpenPicker podemos añadir FileTypeChoices al objeto FileSavePicker que nos permiten indicar los diferentes formatos que el usuario puede elegir para guardar el fichero.
En nuestor ejemplo hemos añadido tipos imagen (png, jpg y bmp).

Hemos utilizado la propiedad SuggestedStartLocation para establecer una ruta inicial donde guardar el archivo.

La propiedad SuggestedFileName la utilizamos para sugerior al usuario un nombre para el archivo a guardar.

FilePicker 5

Puedes descargar el ejemplo realizado:

Hemos analizado lo fácil que es realizar múltiples acciones de interacción con archivos y carpetas de la máquina gracias al contrato de selector de archivos. Hemos aprendido como seleccionar un archivo, múltiples archivos, una carpeta o como guardar ficheros al disco duro del usuario. Recordar, cualquier duda o sugerencia será bienvenida en los comentarios de la entrada.

Más información

Windows 8. Contrato de compartir.

Introducción

Las aplicaciones Windows Store usan contratos y extensiones para interactuar con otras aplicaciones o el propio sistema. Son una de las grandes novedades planteadas en el sistema.

Contratos. Son un acuerdo establecido entre dos o más aplicaciones. Las aplicaciones Windows Store deben incluir declararaciones en el archivo de manifiesto para que puedan comunicarse con Windows y con otras aplicaciones.

Contamos con una gran variedad de contratos entre los que podemos destacar:

  • Buscar: Permite realizar búsquedas en la aplicación e incluso en otras aplicaciones.
  • Reproducir en: Permite reproducir contenido en dispositivos DLNA.
  • Configuración: Permiten gestionar un acceso rápido a la configuración relacionada con la aplicación.
  • Compartir: Permite al usuario compartir información entre aplicaciones. Nos facilita mucho la tarea de compartir contenido ahorrandonos una gran cantidad de código extra. Las aplicaciones que admiten el contrato compartir pueden compartir  contenido con otras aplicaciones que también lo admitan.

Los contratos nos facilitan mucho trabajo ahorrandonos mucha cantidad de código. Además nos permite con suma facilidad cumplir una de las grandes premisas de unas aplicaciones Windows Store. Una aplicación Windows Store debe ser excelente en un único aspecto antes que cumplir en múltiples. Los contratos permiten que las aplicaciones colaboren entre sí por lo que el usuario tiene aplicaciones excelentes sin perder funcionalidad.

Por último, cabe resaltar un detalle muy importante. Todos los contratos están disponibles para el usuario en la barra de Charms (Contratos) disponible en la parte lateral derecha mediante un simple gesto.

Contrato compartir

En una gran cantidad de aplicaciones Windows Store el usuario puede encontrar información de su interés y quiera compartirla con alguien. El contrato de Share nos permite compartir información de manera fácil y rápida.

Una aplicación Windows Store puede admitir la característica de compartir de dos formas. Puede ser una aplicación de origen. Es decir, proporciona contenido a compartir. O puede ser una aplicación de destino que el usuario puede seleccionar como destino del contenido.

El siguiente diagrama es un resumen de cómo funciona el uso compartido de contenido (origen y destino):

Share

Share

¿Qué tipo de información se puede compartir?

  • Texto plano.
  • Enlaces.
  • Texto con formato. HTML.
  • Archivos.
  • Imágenes.

En esta entrada vamos a centrar nuestra atención en el contrato de búsqueda como origen (fuente de información).

Compartir. Origen.

Como siempre solemos hacer vamos a realizar un ejemplo lo más simple posible pero que nos sea válida para lograr nuestros objetivos. La plantilla selecciona para realizar el ejemplo lo más simple posible será “Blank Application”:

Blank Application

Sólo podemos compartir un tipo de datos por cada página. Por ello, vamos a crear un pequeño menú de botones que nos permitirá navegar a diferentes páginas donde vamos a implementar la posibilidad de compartir contenido:

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
     <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
          <Button x:Name="btnShareText" Content="Compartir Texto plano" Height="150" Width="250"/>
          <Button x:Name="btnShareFormattedText" Content="Compartir Texto con formato" Height="150" Width="250"/>
          <Button x:Name="btnShareImage" Content="Compartir Imagen" Height="150" Width="250"/>
          <Button x:Name="btnShareLink" Content="Compartir Enlace" Height="150" Width="250"/>
     </StackPanel>
</Grid>

Tras añadir los botones, añadimos los eventos Click de cada botón:

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
     <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
          <Button x:Name="btnShareText" Content="Compartir Texto plano" Height="150" Width="250" Click="btnShareText_Click"/>
          <Button x:Name="btnShareFormattedText" Content="Compartir Texto con formato" Height="150" Width="250" Click="btnShareFormattedText_Click"/>
          <Button x:Name="btnShareImage" Content="Compartir Imagen" Height="150" Width="250" Click="btnShareImage_Click"/>
          <Button x:Name="btnShareLink" Content="Compartir Enlace" Height="150" Width="250" Click="btnShareLink_Click"/>
     </StackPanel>
</Grid>

El aspecto visual conseguido es algo como lo siguiente:

UI

UI

En el code-behind:

private void btnShareText_Click(object sender, RoutedEventArgs e)
{

}

private void btnShareFormattedText_Click(object sender, RoutedEventArgs e)
{

}

private void btnShareImage_Click(object sender, RoutedEventArgs e)
{

}

private void btnShareLink_Click(object sender, RoutedEventArgs e)
{

}

Cada botón va a permitirnos navegar a una nueva página donde implementaremos el contrato Share para poder compartir un tipo de dato diferente en cada página. Para ello debemos añadir nuevas páginas al proyecto. Creamos una carpeta llamada Views. Dentro de la carpeta agregamos cuatro páginas:

  • Text. En esta página vamos a compartir texto plano. Caso más simple.
  • Link. Compartiremos enlaces.
  • FormattedText. Compartiremos texto con formato. HTML.
  • Image. Compartiremos imagenes.

Añadimos la lógica a cada botón para permitir la navegación:

private void btnShareText_Click(object sender, RoutedEventArgs e)
{
     this.Frame.Navigate(typeof(Text));
}

private void btnShareFormattedText_Click(object sender, RoutedEventArgs e)
{
     this.Frame.Navigate(typeof(FormattedText));
}

private void btnShareImage_Click(object sender, RoutedEventArgs e)
{
     this.Frame.Navigate(typeof(Ejemplo_Contrato_Compartir.Views.Image));
}

private void btnShareLink_Click(object sender, RoutedEventArgs e)
{
     this.Frame.Navigate(typeof(Link));
}

Vamos a analizar el código necesario en cada una de las páginas para compartir:

Texto Plano

Para poder utilizar el contrato Share debemos añadir la referencia al siguiente namespace:

using Windows.ApplicationModel.DataTransfer;

En primer lugar, necesitamos definir un objeto de tipo DataTransferManager.

DataTransferManager _dataTransferManager;

Al entrar en la página (evento OnNavigatedTo) instanciamos el objeto de tipo DataTransferManager. Además, crearemos un controlador de eventos para el evento DataRequested que se lanzará al solicitar datos en la página para ser compartidos:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
     base.OnNavigatedTo(e);
     _dataTransferManager = DataTransferManager.GetForCurrentView();
     _dataTransferManager.DataRequested += _dataTransferManager_DataRequested;
}

Recordar siempre cancelar la suscripción al evento DataRequested al salir de la página (buena práctica):

protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
     base.OnNavigatingFrom(e);
     _dataTransferManager.DataRequested -= _dataTransferManager_DataRequested;
}

Por último, queremos compartir un simple texto. Lo haremos en el método _dataTransferManager_DataRequested:

void _dataTransferManager_DataRequested(DataTransferManager sender, DataRequestedEventArgs args)
{
     string textTitle = "Título a compartir";
     string textSource = "Contenido a compartir. En este ejemplo, texto plano, sin formato.";

     DataPackage data = args.Request.Data;
     data.Properties.Title = textTitle;
     data.SetText(textSource);
}

Simple. Creamos un objeto de tipo DataPackage y establecemos las propiedades básicas donde establecemos el texto plano a compartir tilizando el método SetText.

Enlaces

Para el resto de páginas (enlaces, texto con formato e imagenes) debemos repetir una gran parte de la lógica ya explicada. Crear el objeto de tipo DataTransferManager, instanciarlo al entrar en la página, suscribirnos al evento DataRequested, etc. Por ello, vamos a suprimir dicha repetición centrandonos en la parte cambiante e importante, la lógica dentro del evento DataRequested.

El compartir un enlace es muy similar al compartir texto plano. Creamos un objeto de tipo DataPackage e establecemos propiedades. La gran diferencia es que utilizaremos un objeto tipo Uri para indicar la URL. Establecemos la Uri mediente el método SetUri.

void _dataTransferManager_DataRequested(DataTransferManager sender, DataRequestedEventArgs args)
{
     string textTitle = "Compartir un enlace";

     DataPackage data = args.Request.Data;
     data.Properties.Title = textTitle;

     Uri link = new Uri("https://javiersuarezruiz.wordpress.com");
     data.SetUri(link);
}

HTML

Sin duda una de las formas más extendidas de compartir contenido. Veamos como sería:

void _dataTransferManager_DataRequested(DataTransferManager sender, DataRequestedEventArgs args)
{
     string textTitle = "Título a compartir";
     string formattedTextSource = "Contenido a compartir. En este ejemplo, texto <strong>con</strong> formato.";

     DataPackage data = args.Request.Data;
     data.Properties.Title = textTitle;
     data.SetHtmlFormat(HtmlFormatHelper.CreateHtmlFormat(formattedTextSource));
}

Comenzamos como hasta ahora. Creamos una cadena con setencias HTML. A continuación, creamos un objeto de tipo DataPackage. Establecemos las propiedades donde lo más importante a resaltar que establecemos el texto con formato utilizando el método SetHtmlFormat. El texto con formato se consigue haciendo una llamada a HtmlFormatHelper que recibirá una cadena de texto que convertirá a HTML.

Imágenes

Vamos a ver el código necesario para compartir imagenes:

async void _dataTransferManager_DataRequested(DataTransferManager sender, DataRequestedEventArgs args)
{
     string textTitle = "Título a compartir";
     string textSource = "Contenido a compartir. En este ejemplo, una imagen.";

     DataPackage data = args.Request.Data;
     data.Properties.Title = textTitle;
     data.Properties.Description = textSource;

     DataRequestDeferral waiter = args.Request.GetDeferral();

     StorageFile image = await Package.Current.InstalledLocation.GetFileAsync("Assets\\Logo.png");
     data.Properties.Thumbnail = RandomAccessStreamReference.CreateFromFile(image);
     data.SetBitmap(RandomAccessStreamReference.CreateFromFile(image));

     List<IStorageItem> files = new List<IStorageItem>();
     files.Add(image);
     data.SetStorageItems(files);

     waiter.Complete();
}

Utilizamos el ya conocido objeto DataPackage donde establecemos la imágen a compartir utilizando el método SetBitmap.

Puedes descargar el ejemplo realizado:

En próximas entradas seguiremos analizando el contrato de compartir. Veremos como compartir documentos RTF, archivos, etc. Además, veremos como podemos establecer nuestra aplicación como fuente de información en el contrato de compartir.  Recordar, cualquier duda o sugerencia será bienvenida en los comentarios de la entrada.

Más información