Almacenar credenciales de forma segura con PasswordVault

Un problema al que nos enfrentamos cuando tenemos que almacenar credenciales de nuestros usuarios en una aplicación móvil, es el como hacerlo de forma segura. Por muy seguro que un sistema afirme ser, siempre lo será tanto como su parte menos segura. Por lo que guardar el nombre y password de un usuario en los settings o en el almacenamiento local de nuestra aplicación sin cifrado de ningún tipo, es una negligencia gravísima. Bastará tener acceso al sistema de archivos por parte de un atacante para obtener esos datos.

Existen muchas formas de evitar esto. Y todas pasan de alguna forma por encriptar los datos almacenados. Quizás podríamos pensar que nos podríamos proteger simplemente calculando un hash del password y usar este hash para autentificar a nuestro usuario en el backend. Esto uede funcionar si el servicio de backend que usamos está bajo nuestro control o siendo de terceros admite esta opción. Pero en la gran mayoría de casos el backend nos pedirá un usuario y password. Incluso en el caso de poder usar el hash de un password, almacenarlo en texto plano junto al nombre de usuario es ya una información muy valiosa para un atacante.

En Windows 8.1 y Windows Phone 8.1 (Tanto Windows XAML como Silverlight) disponemos de un API llamada PasswordVault, que representa un almacén seguro para credenciales de usuario. Una aplicación solo podrá acceder a las credenciales almacenadas por ella misma y no a los de otras aplicaciones. Usarla además es realmente sencillo.

PasswordVault nos permite guardar las credenciales de un usuario mediante el método Add, pasándole una instancia de la clase PasswordCredential. El constructor de PasswordCredential nos permite indicar tres valores:

  • Resource, un nombre que identifica la credencial que se está creando.
  • UserName, el nombre del usuario… lógico no?
  • Password, el password.
PasswordCredential
var credential = new PasswordCredential(«AppName_userCredentials», userEmail, userPassword);

Una vez creado, solo tenemos que pasarlo al método Add de nuestra instancia de PasswordVault:

PasswordVault Add method
PasswordVault pVault = new PasswordVault();
pVault.Add(credential);

Y ya hemos guardado nuestras credenciales de forma segura. Para recuperar los datos cuando los necesitemos de nuevo, podemos usar el método FindAllByResource. Este método recibe un parámetro con el nombre de recurso que indicamos al crear la credencial y devuelve una lista con todas las credenciales que coincidan con ese nombre:

FindAllByResource
PasswordVault pVault = new PasswordVault();
var credentials = pVault.FindAllByResource(resourceName);
return credentials.FirstOrDefault();

Es muy importante que, si existe la posibilidad de que al pedir las credenciales, estas no existan, envolvamos la llamada a FindAllByResource en un bloque Try/Catch. En vez de simplemente devolver nulo, el método falla con una excepción si no existen.

Tras obtener la credencial, podremos obtener directamente el nombre de usuario pero para poder acceder al password tendremos primero que usar el método RetrievePassword de la instancia de PasswordCredential con la que estemos trabajando.

RetrievePassword
var credential = credentials.First();
credential.RetrievePassword();

Tras esto podremos acceder al password almacenado usando la propiedad Password de PasswordCredential.

Por último, puede que en algún momento el usuario quiera que dejemos de almacenar sus credenciales, por lo que podremos usar el método Remove, para eliminarlas del PasswordVault.

PasswordVault Remove
var credentials = this.pVault.FindAllByResource(resourceName);
var credential = credentials.First();
if (credential != null)
    this.pVault.Remove(credential);

En este sentido es interesante tener en cuenta algo. Cuando desinstalemos la aplicación, las credenciales guardadas en el PasswordVault no serán eliminadas. Cuando guardamos algo en los settings o el almacenamiento local de nuestra aplicación, al desinstalar se elimina todo. Esto no ocurre con las credenciales guardadas en el PasswordVault, pues usan un almacenamiento central del sistema.

Y esto es todo! Usar PasswordVault es muy fácil y añade un extra de seguridad a nuestra aplicación, así que no hay excusa para no usarlo. Aquí os dejo una aplicación universal de ejemplo con el código MVVM y el servicio de credenciales compartido. Espero que os sea de utilidad.

Un saludo y Happy Coding!

[MATERIALES] Windows phone 8.1, MVVM, behaviors, animations y visual states.

El viernes 20 de Junio estuve con los chicos de RiojaDotNet en Logroño, dando una charla con Asier Tarancon sobre apps universales. Asier hizo una gran introducción a la plataforma y me allanó el terreno para hablar sobre como implementar MVVM en nuestras apps universales y como enriquecerlas con behaviors, animations y visual states.

Aquí os traigo los materiales de la misma. En primer lugar la presentación que usé. Es muy pequeña porque quise sobre todo usar Visual Studio para explicar las cosas:

 

Y a continuación los ejemplos de behaviors, animations y visual states.

Espero que os sean útiles.

Un saludo y Happy Coding!

[Windows Phone 8.1] Trio de ases: Behaviors, Animations y VisualStates (3)

Y llegamos al último artículo de esta serie, tras ver como trabajar con behaviors y animaciones, en esta ocasión vamos a hablar de los estados visuales.

Los VisualStates nos permiten definir diferentes estados para nuestra página o control para cambiar su apariencia e incluso su funcionalidad. Por ejemplo en una página donde el usuario puede ver un resumen de datos y tiene la opción de editarlos, podemos crear un VisualState de solo lectura y otro de edición, cambiando propiedades de los controles en cada uno de ellos para modificar la forma en la que el usuario interactúa con la página.

También, como vamos a ver en el ejemplo de este artículo, podemos crear estados visuales que modifiquen la interface de usuario dependiendo de la orientación del dispositivo. De esta forma podemos ofrecer al usuario la mejor experiencia en cada momento.

Los VisualStates usan animaciones para modificar los controles a los que quieren afectar y podemos usar behaviors para iniciar el proceso de cambio de uno a otro.

Por regla general, los VisualStates de una página se definirán en la primera Grid que contenga la página. Para ello incorporaremos el nodo, que debe ser el primero dentro de la Grid, VisualStateManager para definir los grupos y los estados de cada grupo:

VisualStateManager
<Grid>
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name=«LayoutStates»>
            <VisualState x:Name=«Landscape»>

            </VisualState>
            <VisualState x:Name=«Portrait»>

            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>

</Grid>

Tras definir el nodo VisualStateManager.VisualStateGroups, definimos los grupos que necesitemos, en este caso uno. El nombre, LayoutStates, es libre y a nuestra elección. Por claridad deberíamos indicar un nombre descriptivo de la finalidad del grupo. En este caso este grupo contiene dos estados, Landscape y Portrait, nombres también a nuestra elección. Si quisiésemos tener otro grupo, podríamos ponerlo a continuación de este con sus correspondientes estados.

En este ejemplo, tenemos una lista de imágenes y queremos variar la forma de mostrarlas al usuario dependiendo de la orientación del dispositivo. Cuando estemos en horizontal, queremos usar un FlipView que haga uso de toda la pantalla. Por el contrario cuando la orientación sea vertical, queremos usar una GridView que muestre las imágenes en una cuadrícula. Así mismo, cuando estemos en vertical queremos que al hacer click en las imágenes aparezca un popup con la imagen seleccionada. Nuestro XAML quedaría más o menos así:

 

XAML
<GridView x:Name=«ListImages» ItemsSource=»{Binding Images}«>
    <GridView.ItemTemplate>
        <DataTemplate>
            <Grid Width=«150» Height=«150» Margin=«0»>
                <Image Stretch=«UniformToFill» Source=»{Binding }«/>
            </Grid>
        </DataTemplate>
    </GridView.ItemTemplate>
    <i:Interaction.Behaviors>
        <core:EventTriggerBehavior EventName=«SelectionChanged»>
            <core:GoToStateAction StateName=«BigImage»/>
        </core:EventTriggerBehavior>
    </i:Interaction.Behaviors>
</GridView>

<Grid x:Name=«Popup» Visibility=«Collapsed» Background=«#AA555555» VerticalAlignment=«Stretch» HorizontalAlignment=«Stretch»>
    <Image Margin=«40» Stretch=«Uniform» Source=»{Binding SelectedItem, ElementName=ListImages}«>
    </Image>
    <i:Interaction.Behaviors>
        <core:EventTriggerBehavior EventName=«Tapped»>
            <core:GoToStateAction StateName=«NormalState»/>
        </core:EventTriggerBehavior>
    </i:Interaction.Behaviors>
</Grid>

<FlipView x:Name=«flipImages» Visibility=«Collapsed» ItemsSource=»{Binding Images}« SelectedItem=»{Binding SelectedItem, ElementName=ListImages}«>
    <FlipView.ItemTemplate>
        <DataTemplate>
            <Image Stretch=«Uniform» Source=»{Binding }«></Image>
        </DataTemplate>
    </FlipView.ItemTemplate>
</FlipView>

 

Como vemos, simplemente tenemos todos los controles necesarios: un GridView, una Grid llamada Popup y por último un FlipView. Por defecto tanto el popup como el FlipView tienen su visibilidad establecida a Collapsed. Lo que vamos a hacer es, en cada VisualState, mostrar u ocultar los controles que nos interesen en cada momento:

VisualState Landscape
<VisualState x:Name=«Landscape»>
    <Storyboard>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName=«ListImages» Storyboard.TargetProperty=«Visibility»>
            <DiscreteObjectKeyFrame KeyTime=«0:0:0» Value=«Collapsed»/>
        </ObjectAnimationUsingKeyFrames>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName=«flipImages» Storyboard.TargetProperty=«Visibility»>
            <DiscreteObjectKeyFrame KeyTime=«0:0:0» Value=«Visible»/>
        </ObjectAnimationUsingKeyFrames>
    </Storyboard>
</VisualState>

 

VisualState Portrait
<VisualState x:Name=«Portrait»>
    <Storyboard>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName=«ListImages» Storyboard.TargetProperty=«Visibility»>
            <DiscreteObjectKeyFrame KeyTime=«0:0:0» Value=«Visible»/>
        </ObjectAnimationUsingKeyFrames>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName=«flipImages» Storyboard.TargetProperty=«Visibility»>
            <DiscreteObjectKeyFrame KeyTime=«0:0:0» Value=«Collapsed»/>
        </ObjectAnimationUsingKeyFrames>
    </Storyboard>
</VisualState>

 

Así, en el caso del VisualState Landscape, cambiamos la visibilidad del GridView a Collapsed y la del FlipView a Visibile. En el Portrait lo contrario, mostramos el GridView y ocultamos el FlipView.

¿Y como lanzamos cada VisualState? Tenemos que hacerlo manualmente. Detectar el cambio de orientación y cambiar al VisualState que corresponda. Aquí es donde los behaviors vienen en nuestra ayuda. En concreto vamos a servirnos del Behavior DataTriggerBehavior. En nuestra ViewModel vamos a acceder a la clase DisplayInformation, que nos ofrece la propiedad CurrentOrientation y el evento OrientationChanged. Analizando los datos que nos ofrecen vamos a exponer una propiedad llamada IsLandscape:

DisplayInformation
public VMMain()
{
    var dInfo = DisplayInformation.GetForCurrentView();
    if (dInfo.CurrentOrientation == DisplayOrientations.Landscape || dInfo.CurrentOrientation == DisplayOrientations.LandscapeFlipped)
        IsLandscape = true;
    else
        IsLandscape = false;

    dInfo.OrientationChanged += dInfo_OrientationChanged;
}

Luego en XAML, usaremos el DataTriggerBehavior para ver si esta propiedad es true, momento en el que usaremos el GoToStateAction para cambiar al estado Landscape, o false, para cambiar al estado Portrait:

DataTriggerBehavior
<i:Interaction.Behaviors>
    <core:DataTriggerBehavior Binding=»{Binding IsLandscape}« ComparisonCondition=«Equal» Value=«true»>
        <core:GoToStateAction StateName=«Landscape»/>
    </core:DataTriggerBehavior>
    <core:DataTriggerBehavior Binding=»{Binding IsLandscape}« ComparisonCondition=«Equal» Value=«false»>
        <core:GoToStateAction StateName=«Portrait»/>
    </core:DataTriggerBehavior>
</i:Interaction.Behaviors>

Y Voila! Si ejecutamos nuestra aplicación en el simulador de Windows 8.1 o el emulador de Windows Phone 8.1, veremos que al cambiar la orientación, automáticamente cambia la apariencia de nuestra aplicación. Además, como todo lo visto en los artículos anteriores, los VisualStates son también totalmente compatibles entre Windows Phone y Windows Store, por lo que el ejemplo incluido en este artículo es una aplicación universal que comparte el 100% del código C# y XAML usado:

image

Las aplicaciones de los VisualStates son muchas. Pero lo más importante es que nos ofrecen una forma sencilla de cambiar el aspecto de nuestra página. De echo, si editas la plantilla por defecto de cualquier control de XAML, verás que usa VisualStates para definir estados como Focus, Tapped, o Selected.

Y con esto llegamos al final de este artículo y de la serie. Espero que haya sido útil para ver una forma nueva de trabajar con el aspecto visual de nuestra página, lanzar acciones en respuesta a las del usuario y crear bonitas animaciones. Como siempre, aquí puedes descargar este último ejemplo para usarlo como referencia.

Un saludo y Happy Coding!!

 

[Windows Phone 8.1] Trio de ases: Behaviors, Animations y VisualStates (2)

En el artículo anterior de esta serie hablamos sobre el behavior SDK, una herramienta que nos permitía realizar ciertas acciones directamente en XAML y sin necesidad de escribir código C# en respuesta a cambios de datos o lanzamiento de eventos. En este, vamos a ver otra herramienta que XAML pone a nuestra disposición: las animaciones.

En todo desarrollo existe algo en lo que debemos poner toda nuestra atención: fluidez. Que nuestra aplicación se comporte rápido y de forma fluida es muy importante. Pero muchas veces, podemos dividir la fluidez en dos conceptos: fluidez real y fluidez percibida. Y contrariamente a lo que pudiésemos pensar, es la segunda, la fluidez percibida, la más importante. Por su puesto que es muy importante que nuestra aplicación sea fluida y rápida. Pero siempre existirán puntos, como ciertos procesos de carga, que serán inevitables. Si aderezamos esos momentos con una distracción para el usuario, desviando su atención del tiempo exacto que tardamos en cargar datos, conseguiremos que este perciba la aplicación como más fluida y rápida de lo que realmente es.

Pongamos un ejemplo. Imaginad que tras cargar la página principal de nuestra aplicación y mostrarla en pantalla debemos llamar a un servicio web para obtener ciertos datos necesarios. aquí el truco para dar fluidez a la aplicación es muy sencillo: Primero mostramos la página con todo el contenido estático que podamos, para a continuación en otro hilo cargar los datos del servicio. La página principal se carga rápido, la interface no se bloquea. Podemos decir que nuestra aplicación es fluida. Pero realmente, existe un ligero desfase, en el que el usuario ve la barra de carga de la aplicación, quizás durante 500 milisegundos o un segundo. Aunque se ha cargado todo sin bloquear nada, el usuario ha tenido que esperar casi un segundo para poder empezar a usar nuestra aplicación. Bien, si sabemos que ese tiempo oscila entre 500 y 1000 milisegundos, aprovechémoslo. Por ejemplo podríamos hacer que al cargarse la pantalla, los elementos estáticos en vez de aparecer ya posicionados, vayan apareciendo en una sucesión, tener una imagen como la splash screen sobre la página que animemos para que desaparezca con un fade out, o algo por el estilo. Si ajustamos esta animación a 750 milisegundos por ejemplo, por debajo podemos al mismo tiempo pedir los datos al servicio. El resultado es que: En el mejor de los casos cuando la animación acabe la página estará operativa. En el peor de los casos quizás el usuario tendrá que esperar unos 250 milisegundos a obtener todo. Pero fijaros que hemos pasado de una espera de 500 a 1000 milisegundos a otra de entre 0 y 250 milisegundos. No hemos hecho que nuestra aplicación sea más rápida, pero si hemos mejorado la fluidez percibida. Todo esto gracias además a que las animaciones en XAML son totalmente asíncronas, mientras no bloqueemos el hilo de interface de usuario, podemos ejecutar código al mismo tiempo que lanzamos una animación. ¿Qué os parece el truco?

Además de esta utilidad “práctica”, las animaciones también cumplen un papel claramente estético. usar una pequeña y simple animación para mostrar un elemento o resaltarlo, como veremos hoy, pueden mejorar el aspecto de nuestra aplicación muchísimo. Así que empecemos a meternos en faena, viendo como crear animaciones en Windows Phone 8.1, Windows 8.1 y apps universales.

Storyboard, Animations y KeyFrames.

Toda animación en XAML se encuadra dentro de un elemento Storyboard. El elemento Storyboard define la duración, el auto rebobinado, el comportamiento de repetición y más cosas mediante varias propiedades:

  • Duration. Nos permite expresar el tiempo como un TimeSpan (hh:mm:ss.ms) se trata del tiempo total que va a durar la animación en completarse.
  • BeginTime. Expresa, también como un TimeSpan, el tiempo a esperar, una vez comenzada la ejecución de la animación, antes de ejecutar el primer frame. Es muy útil si queremos lanzar y sincronizar o encadenar distintas animaciones.
  • FillBehavior. Aporta dos opciones: HoldEnd y Stop. Indica el comportamiento a llevar a cabo al terminar la animación. HoldEnd es el valor por defecto y mantiene la animación en el último cuadro de la misma. Stop para la animación y vuelve al estado inicial.
  • AutoReverse: indica si al terminar se debe ejecutar la animación al revés automáticamente.
  • RepeatBehavior: Permite especificar el comportamiento de repetición: Puede contener un número que indica el número de veces que se repetirá la animación, 0 para nunca, o la palabra Forever, que indica que nunca dejará de repetirse a no ser que la paremos explícitamente.
  • SpeedRatio. La velocidad de reproducción. Podemos considerarlo como un avance rápido de la animación.

La clase Storyboard también contiene dos métodos: Begin y Pause, que nos permiten comenzar o parar la reproducción de la animación. Así mismo dispondremos del evento Completed para saber cuando ha terminado. En XAML, Un Storyboard con una duración de 2 segundos, 1 repetición y auto rebobinado tendría este aspecto:

Sample storyboard
<Storyboard x:Key=«SampleStoryboard» RepeatBehavior=«1» Duration=«0:0:2» AutoReverse=«True»>
</Storyboard>

Al declarar un Storyboard usamos el identificador x:Key. Esto se debe a que una Storyboard es un recurso, ya sea de la aplicación, de la página o de un control.

Lo siguiente que tenemos que hacer es definir la colección de animaciones a usar en el Storyboard. Disponemos de diferentes tipos de animaciones, dependiendo del tipo de la propeidad que deseemos modificar. De cada tipo existen dos variantes: Una variante simple, que nos permite indicar un valor final y una duración y una variante más completa que nos permite definir una colección de cuadros para la animación:

  • DoubleAnimation / DoubleAnimationUsingKeyFrames, para animar propiedades numéricas.
  • ColorAnimation / ColorAnimationUsingKeyFrames, para animar propiedades basadas en colores.
  • PointAnimation / PointAnimationUsingKeyFrames, para animar propiedades basadas en puntos.
  • ObjectAnimationUsingKeyFrames, para animar cualquier otro tipo de propiedad.

Dentro de la animación usaremos las propiedades Storyboard.TargetName y Storyboard.Property para definir el elemento y la propiedad que deseamos animar. En este sentido debemos tener en cuenta que, en un mismo Storyboard no podremos definir dos animaciones distintas para una misma propiedad de un mismo elemento. Esto no es problema puesto que al poder usar KeyFrames, dentro de una animación podemos definir tantos cambios como queramos. Por ejemplo podemos animar la propiedad Opacity de un elemento de la siguiente forma usando una DoubleAnimationUsingKeyFrames:

DoubleAnimationUsingKeyFrames
<Storyboard x:Key=«SampleStoryboard» RepeatBehavior=«1» Duration=«0:0:2» AutoReverse=«True»>
    <DoubleAnimationUsingKeyFrames Storyboard.TargetName=«ScoreCard» Storyboard.TargetProperty=«Opacity»>
    </DoubleAnimationUsingKeyFrames>
</Storyboard>

A continuación ya solo nos queda definir los frames de la animación. Cada frame es un instante en el tiempo de la animación en el que definimos un valor para la propiedad que estamos animando. Cada tipo de animación soporta cuatro tipos de frames:

  • Linear, que usa una interpolación lineal entre frames para animar la propiedad.
  • Discrete, que usa una interpolación discreta entre frames para animar la propiedad.
  • Easing, que usa una función de easing para modificar la interpolación entre frames.
  • Spline que usa un Spline para definir la interpolación entre frames.

Normalmente utilizaremos Lineal y Easing dependiendo de si queremos una animación uniforme o aplicar efectos de rebote, aceleración o deceleración entre cuadros. El uso es el mismo en ambos casos, debemos indicar el tiempo dentro del Storyboard en el que deseamos ejecutar cada frame y el valor que debe tener la propiedad animada en ese momento. A mayores, en el caso del Easing podremos indicar una función de easing para aplicar el efecto deseado:

 

LinearDoubleKeyFrame
<Storyboard x:Key=«SampleStoryboard» RepeatBehavior=«1» Duration=«0:0:2» AutoReverse=«True»>
    <DoubleAnimationUsingKeyFrames Storyboard.TargetName=«ScoreCard» Storyboard.TargetProperty=«Opacity»>
        <LinearDoubleKeyFrame KeyTime=«0:0:2» Value=«1»/>
    </DoubleAnimationUsingKeyFrames>
</Storyboard>

 

 

EasingDoubleKeyFrame
<Storyboard x:Key=«SampleStoryboard» RepeatBehavior=«1» Duration=«0:0:2» AutoReverse=«True»>
    <DoubleAnimationUsingKeyFrames Storyboard.TargetName=«ScoreCard» Storyboard.TargetProperty=«Opacity»>
        <EasingDoubleKeyFrame KeyTime=«0:0:2» Value=«1»>
            <EasingDoubleKeyFrame.EasingFunction>
                <CubicEase EasingMode=«EaseOut»/>
            </EasingDoubleKeyFrame.EasingFunction>
        </EasingDoubleKeyFrame>
    </DoubleAnimationUsingKeyFrames>
</Storyboard>

 

Y ya tenemos lista nuestra animación. En ambos casos animamos la propiedad Opacity de un elemento llamado ScoreCard hasta un valor de 1. No indicamos el valor inicial de la propiedad, así la animación tomará como valor inicial el que tenga la propiedad en el momento en que se ejecute la animación. En el caso del EasingDoubleKeyFrame además definimos la función de easing, un Cubic ease en modo out. Esto hace que la animación haga un efecto de aceleración.

Como hemos mencionado antes, dentro de un Storyboard podemos definir distintas animaciones para conseguir efectos más complejos. Incluso podemos combinar distintas animaciones (jugando con la propiedad BeginTime). En el ejemplo adjunto a este artículo tenemos una animación que cambia el color y la escala de un TextBlock con un número y además muestra unos rayos girando a toda pantalla:

image

Los rayos no aparecen de golpe, se anima el tamaño y la opacidad para que aparezcan expandiéndose y luego girando. El código de la animación completa es el siguiente:

Rays animation
<Page.Resources>
    <Storyboard x:Key=«ShowSuccess»>
        <DoubleAnimationUsingKeyFrames Storyboard.TargetName=«Rays» Storyboard.TargetProperty=«Opacity»>
            <EasingDoubleKeyFrame KeyTime=«0:0:0.5» Value=«.5»>
                <EasingDoubleKeyFrame.EasingFunction>
                    <CubicEase EasingMode=«EaseOut»/>
                </EasingDoubleKeyFrame.EasingFunction>
            </EasingDoubleKeyFrame>
        </DoubleAnimationUsingKeyFrames>
        <DoubleAnimationUsingKeyFrames Storyboard.TargetName=«Rays» Storyboard.TargetProperty=«(UIElement.RenderTransform).(CompositeTransform.ScaleY)»>
            <EasingDoubleKeyFrame KeyTime=«0:0:0.5» Value=«15»>
                <EasingDoubleKeyFrame.EasingFunction>
                    <CubicEase EasingMode=«EaseOut»/>
                </EasingDoubleKeyFrame.EasingFunction>
            </EasingDoubleKeyFrame>
        </DoubleAnimationUsingKeyFrames>
        <DoubleAnimationUsingKeyFrames Storyboard.TargetName=«Rays» Storyboard.TargetProperty=«(UIElement.RenderTransform).(CompositeTransform.ScaleX)»>
            <EasingDoubleKeyFrame KeyTime=«0:0:0.5» Value=«15»>
                <EasingDoubleKeyFrame.EasingFunction>
                    <CubicEase EasingMode=«EaseOut»/>
                </EasingDoubleKeyFrame.EasingFunction>
            </EasingDoubleKeyFrame>
        </DoubleAnimationUsingKeyFrames>
        <DoubleAnimationUsingKeyFrames Storyboard.TargetName=«ScoreCard» Storyboard.TargetProperty=«(UIElement.RenderTransform).(CompositeTransform.ScaleX)»>
            <EasingDoubleKeyFrame KeyTime=«0:0:0.3» Value=«1.2»>
                <EasingDoubleKeyFrame.EasingFunction>
                    <CubicEase EasingMode=«EaseOut»/>
                </EasingDoubleKeyFrame.EasingFunction>
            </EasingDoubleKeyFrame>
        </DoubleAnimationUsingKeyFrames>
        <DoubleAnimationUsingKeyFrames Storyboard.TargetName=«ScoreCard» Storyboard.TargetProperty=«(UIElement.RenderTransform).(CompositeTransform.ScaleY)»>
            <EasingDoubleKeyFrame KeyTime=«0:0:0.3» Value=«1.2»>
                <EasingDoubleKeyFrame.EasingFunction>
                    <CubicEase EasingMode=«EaseOut»/>
                </EasingDoubleKeyFrame.EasingFunction>
            </EasingDoubleKeyFrame>
        </DoubleAnimationUsingKeyFrames>
        <DoubleAnimationUsingKeyFrames Storyboard.TargetName=«ScoreCard» Storyboard.TargetProperty=«Opacity»>
            <EasingDoubleKeyFrame KeyTime=«0:0:0.3» Value=«1»>
                <EasingDoubleKeyFrame.EasingFunction>
                    <CubicEase EasingMode=«EaseOut»/>
                </EasingDoubleKeyFrame.EasingFunction>
            </EasingDoubleKeyFrame>
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>
    <Storyboard x:Key=«AnimateRays» RepeatBehavior=«Forever» BeginTime=«0:0:0.1» FillBehavior=«HoldEnd» >
        <DoubleAnimationUsingKeyFrames EnableDependentAnimation=«True» Storyboard.TargetName=«Rays» Storyboard.TargetProperty=«(UIElement.RenderTransform).(CompositeTransform.Rotation)»>
            <LinearDoubleKeyFrame KeyTime=«0:0:12» Value=«500»/>
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>
</Page.Resources>

Quizás lo más extraño de esta animación es la forma de definir las propiedades. en vez de usar una propiedad del elemento estamos usando una transformación para poder rotarlo o escalarlo, por eso la animación se define como (UIElement.RenderTransform).(CompositeTransform.ScaleY):

  • (UIElement.RenderTransform) Aquí indicamos que de un UIElement (Todos los elementos en XAML heredan de la clase base UIElement), deseamos acceder a su propiedad RenderTransform.
  • (CompositeTransfrom.ScaleY) indicamos que dentro de la propiedad RenderTransform tenemos definido un CompositeTransform y que deseamos animar la propiedad ScaleY del composite transform.

En el TextBlock ScoreCard, definimos el RenderTransform de la siguiente forma:

CompositeTransform
<TextBlock x:Name=«ScoreCard» Text=»{Binding ScoreValue, Mode=TwoWay}« FontSize=«64» Width=«130» Height=«70»
           TextAlignment=«Center» FontWeight=«Bold» Grid.Row=«1» Opacity=«.5» VerticalAlignment=«Center»
           HorizontalAlignment=«Center»>
    <TextBlock.RenderTransform>
        <CompositeTransform CenterX=«65» CenterY=«35» ScaleX=«1» ScaleY=«1»/>
    </TextBlock.RenderTransform>
</TextBlock>

Por último, solo nos queda iniciar las animaciones en el momento justo. Aquí es donde entran en juego los behaviors que explicamos en el artículo anterior. En este caso podemos hacer uso de la acción ControlStoryboardAction del namespace Microsoft.Xaml.Interaction.Media. Como disparador, podemos usar el click de un botón:

ControlStoyboardAction (1)
<Button Content=«play»>
    <i:Interaction.Behaviors>
        <core:EventTriggerBehavior EventName=«Tapped»>
            <media:ControlStoryboardAction ControlStoryboardOption=«Play» Storyboard=»{StaticResource ShowSuccess}«/>
            <media:ControlStoryboardAction ControlStoryboardOption=«Play» Storyboard=»{StaticResource AnimateRays}«/>
        </core:EventTriggerBehavior>
    </i:Interaction.Behaviors>
</Button>

Simplemente indicamos el evento, Tapped, y lo que queremos hacer con cada Storyboard (Play, Pause, Stop…) y por último el Storyboard afectado y listo! Pero pensemos por un momento, que queremos mostrar esta animación cuando el usuario completa el 100% de una tarea o llega a un hito concreto en nuestra aplicación. Para esto, podemos usar el disparador basado en datos (DataTiggerBehavior). Lo podemos definir por ejemplo en el TextBlock ScoreCard:

ControlStoryboardAction(2)
<TextBlock x:Name=«ScoreCard» Text=»{Binding ScoreValue, Mode=TwoWay}« FontSize=«64» Width=«130» Height=«70»
           TextAlignment=«Center» FontWeight=«Bold» Grid.Row=«1» Opacity=«.5» VerticalAlignment=«Center»
           HorizontalAlignment=«Center»>
    <TextBlock.RenderTransform>
        <CompositeTransform CenterX=«65» CenterY=«35» ScaleX=«1» ScaleY=«1»/>
    </TextBlock.RenderTransform>
    <i:Interaction.Behaviors>
        <core:DataTriggerBehavior Binding=»{Binding ScoreValue}« ComparisonCondition=«GreaterThanOrEqual» Value=«100»>
            <media:ControlStoryboardAction ControlStoryboardOption=«Play» Storyboard=»{StaticResource ShowSuccess}«/>
            <media:ControlStoryboardAction ControlStoryboardOption=«Play» Storyboard=»{StaticResource AnimateRays}«/>
        </core:DataTriggerBehavior>
    </i:Interaction.Behaviors>
</TextBlock>

En este caso, indicamos al DataTriggerBehavior la propiedad que nos interesa de nuestra ViewModel (ScoreValue), la condición de comparación que debe cumplir (GreaterThanOrEqual) y el valor contra el que compararlo (100 en este caso).

En nuestra ViewModel, simplemente incrementamos la propiedad y notificamos el cambio:

ScoreValue
public int ScoreValue
{
    get { return this.scoreValue; }
    set
    {
        this.scoreValue = value;
        RaisePropertyChanged();
    }
}

Sin tener que escribir ningún código extra, cuando la propiedad ScoreValue llegue a 100, se ejecutará la animación ShowSuccess y AnimateRays. Como podemos observar, este último método nos ofrece la gran ventaja de hacer que nuestras vistas sean más ricas y reaccionen de forma animada a los cambios de los datos de nuestras ViewModels, abriendo un gran abanico de posibilidades para nuestra UI.

Por supuesto, algo a tener muy en cuenta es que, al igual que pasa con los behaviors, el sistema de animación es totalmente universal y compartido entre Windows phone y Windows store. De echo, todo el código de este artículo está compartido en un proyecto universal: la página, las animaciones y las viewmodels. No hay ni una sola línea de código C# o XAML en los proyectos específicos de la plataforma.

Y hasta aquí llega este segundo artículo. En el próximo colocaremos la última pieza de este trio de ases, los VisualStates, que nos permitirán crear páginas totalmente adaptables al momento, datos, situación… Pero para eso todavía os haré esperar un poco más. Mientras tanto, podéis descargaros de aquí el código completo y funcional de este artículo y ejecutarlo para ver lo bien que quedan las animaciones y lo sencilla que es hacerlas.

Un saludo y Happy Coding!!

[Windows Phone 8.1] Trio de ases: Behaviors, Animations y VisualStates (1)

Hola a todos!

Hoy vamos a comenzar a dar un repaso a un trio clásico de XAML que nos ayudará a crear mejores apps tanto para Windows Phone 8.1 como para Windows Store y Universal Apps. Hablo sin duda del equipo formado por los behaviors, las animaciones y los visual states.

Behaviors

Los behaviors (o comportamientos, si queréis traducirlo) nos permiten agregar cierta inteligencia a nuestro XAML para que realice acciones sin tener que escribir código para ello. Con Windows 8.1 se introdujo una extensión llamada Behaviors SDK, que ahora tenemos disponible también en Windows Phone 8.1, exactamente con la misma funcionalidad.

Podríamos dividir su uso en dos grandes bloques. Por un lado tenemos los triggers, que nos permiten definir la situación bajo la cual nuestros behaviors deben ser ejecutados. Por otro tenemos los behaviors y las activities propiamente dichos, que nos permiten definir qué hacer cuando se active el trigger.

En cuanto a triggers, tenemos los siguientes tipos:

  • DataTriggerBehavior. Este trigger nos permite ejecutar behaviors basándonos en datos para definir cuando comenzar la ejecución. Dispone de varias propiedades para definir el momento del lanzamiento:
    • Binding: Nos permite definir un enlace a una propiedad de otro objeto/ViewModel para usar su valor como base de la ejecución.
    • ComparisonCondition: Se trata de un enumerado en el que podemos definir como observar el valor de binding: Equal, GreaterThan, GreaterThanOrEqual, LessThan, LessThanOrEqual y NotEqual.
    • Value: el valor contra el que comparar el Binding.
  • EventTriggerBehavior. Nos permite definir un evento, que al lanzarse, ejecutará nuestros behaviors. Dispone de una propiedad EventName, donde podremos definir el nombre del evento que queremos escuchar y SourceObject, donde podremos definir el objeto de origen del evento, en caso de que sea distinto del objeto que contiene al trigger.

Y por el lado de los behaviors, encontramos los siguientes:

  • IncrementalUpdateBehavior. Un gran desconocido pero muy útil, sobre todo si trabajamos con grandes listas. Dentro de un DataTemplate de un ListView o GridView, nos permite definir diferentes “fases” de carga de los controles que lo componen. De esta forma, al hacer scroll, la carga de los diferentes elementos y su visualización se realizará en secuencia. Por ejemplo, podemos tener una DataTemplate que muestre un texto y una foto. Con este behavior, en su propiedad Phase, podemos  establecer la fase 1  al texto y la 2 a la imagen. Al hacer scroll, la lista mostrará primero los textos y a continuación cargará la imagen, lo que nos dará mayor fluided.
  • CallMethodAction. Como su nombre bien indica, nos permite ejecutar un método. Contiene una propiedad MethodName, donde podemos definir el nombre del método a ejecutar y una propiedad TargetObject, donde podremos definir un enlace a datos al objeto que contiene el método. Importante tener en cuenta que el método debe ser público para poder ejecutarlo.
  • GoToStateAction. Nos permite cambiar nuestro VisualState actual, definiendo el nombre del estado nuevo en la propiedad StateName, el objeto que lo contiene en la propiedad TargetObject y si deseamos usar transiciones entre el estado actual y el nuevo, con la propiedad UseTransitions. Más adelante cuando examinemos los VisualStates, veremos la potencia de este behavior.
  • InvokeCommandAction. Ejecuta el comando indicado. Disponemos de una propiedad Command, donde podemos definir el comando al igual que haríamos en un elemento Button y CommandParameter, que nos permite definir un parámetro.
  • NavigateToPageAction. Nos permite iniciar la navegación a una página. En la propiedad TargetPage debemos indicar el nombre cualificado completo de la clase de la página a la que queremos navegar, mientras que la propiedad Parameter nos permite indicar un parámetro que se enviará a dicha página.
  • ControlStoryboardAction. Como su nombre bien indica, este behavior nos ayudará a controlar una Storyboard, que como veremos más adelante es la base de cualquier animación en XAML. Dispone de una propiedad ControlStoryboardOption, donde podremos definir el tipo de acción que deseamos realizar: Play, Pause, Resume, SkipToFill, Stop, TogglePlayPause… También disponemos de la propiedad Storyboard, donde podremos indicar la Storyboard que deseamos controlar.
  • PlaySoundAction. Reproducción de sonido, dispone de una propiedad Source, donde definiremos el path del archivo de sonido a reproducir y una propiedad Volume, donde podremos definir el volumen de reproducción.

Como podemos ver, si combinamos los distintos tipos de behaviors con los tiggers, disponemos de una amplia gama de acciones a realizar bajo diferentes condiciones sin necesidad de añadir código C#. Podemos poner como ejemplo:

  • Ejecutar una animación cuando una propiedad boolean de nuestra ViewModel sea True.
  • Navegar a una página distinta cuando el usuario haga click en una imagen.
  • Reproducir un sonido al cambiar el elemento seleccionado de una lista.
  • Invocar a un comando o un método cuando cierto número de elementos haya sido cargado.
  • Cambiar el VisualState en respuesta a un cambio en los datos de nuestra ViewModel.

Bien, ¿Y como se usan? Primero debemos añadir una referencia al Behavior SDK que se incluye por defecto para Windows Phone 8.1 y Windows Store 8.1. Para ello solo tendremos que pulsar el botón derecho sobre nuestro proyecto, seleccionar Add Reference e ir al nodo de Extensions y marcar la extensión “Behaviors SDK (XAML)” como podemos ver en la imagen a continuación:

image

Una vez hecho esto, tendremos que añadir los namespaces Microsoft.Xaml.Interactivity, Microsoft.Xaml.Interaction.Core y Microsoft.Xaml.Interaction.Media a nuestra página o user control:

Namespaces
xmlns:i=«using:Microsoft.Xaml.Interactivity»
xmlns:core=«using:Microsoft.Xaml.Interactions.Core»
xmlns:media=«using:Microsoft.Xaml.Interactions.Media»

Y ya podremos empezar a usar los behaviors. Por ejemplo, Si tenemos dos paginas en nuestro proyecto, MainPage y SecondaryPage, podemos usar el behavior NavigateToPageAction en conjunción con el trigger EventTriggerBehavior para navegar de MainPage a SecondaryPage al hacer tap sobre una imagen:

NavigateToPageAction
<Grid>
    <Image Source=«/assets/picture.jpg» Width=«300»>
        <i:Interaction.Behaviors>
            <core:EventTriggerBehavior EventName=«Tapped»>
                <core:NavigateToPageAction TargetPage=«BehaviorsSample.SecondaryPage»/>
            </core:EventTriggerBehavior>
        </i:Interaction.Behaviors>
    </Image>
</Grid>

La utilización es muy simple y siempre igual para todos los behaviors. Dentro de un elemento definimos un hijo de tipo Interaction.Behaviors, que se encuentra en el namespace Microsoft.Xaml.Interactivity, a continuación el trigger a usar, definido en Microsoft.Xaml.Interactions.Core y por último la acción a realizar por el behavior.

Además, como son exactamente iguales en Windows Store y Windows Phone, podemos compartir el XAML donde los usemos en la carpeta shared de un proyecto universal sin problemas.

En el siguiente artículo de la serie, veremos las animaciones y volveremos a hablar de los behaviors y los triggers, como una fantástica forma de lanzar animaciones basándonos en datos y eventos, sin tener que escribir código extra para manejarlas.

Por ahora, aquí podréis descargar el ejemplo de hoy para que empecéis a practicar con los behaviors y ver la potencia que encierran. Como en el ejemplo, ser capaces de integrar en vuestras aplicaciones navegación, basada en eventos, sin tener que crear un servicio de navegación, comandos ni eventos.

Un saludo y Happy Coding!

[Windows Phone 8.1] WebAuthenticationBroker

Hola a todos!

Después de unos días sin escribir y de que se presentase oficialmente la RTM del SDK de Windows Phone 8.1, volvemos a la carga con novedades en las APIs de Windows Phone 8.1. En esta ocasión quiero hablar del WebAuthenticationBroker. Los que hayáis trabajado con apps Windows Store, lo conoceréis sin duda. Para el resto, aquí va una introducción.

¿Qué es el WebAuthenticationBroker?

El WebAuthenticationBroker es una clase pensada para facilitarnos la vida como desarrolladores a la hora de usar sistemas de autenticación OAuth de cualquier tipo. Facebook, Twitter, LinkedIn… casi toda empresa que expone APIs públicas usa OAuth como sistema de identificación. Básicamente este sistema nos permite registrar nuestra app en él y obtener unos identificadores para la misma. Luego, en tiempo de ejecución nuestra aplicación abre una web del sistema, enviando los identificadores recibidos a la misma y en la que se pide al usuario que introduzca su nombre y clave para autorizar a nuestra aplicación a acceder a su cuenta. Lo bueno de esto es que el usuario no introduce sus datos en nuestra aplicación, lo hace en una web del creador del API, por lo que su confianza debería ser mayor. Al final, nuestra aplicación recibe un token, normalmente con un tiempo de vida predeterminado, que podemos usar para autentificar las llamadas al API que realicemos. Además, el usuario puede revocarnos el acceso desde la administración del API en cualquier momento. A continuación os muestro un esquema, OAuth tiene un funcionamiento interno que en este esquema simplifico para enseñar como se relaciona con nuestra aplicación, no como funciona internamente que está fuera del alcance de este artículo:

image

Como podemos ver, simplemente hacemos una petición a una URL OAuth. En realidad navegamos a esa URL, lo cual muestra la web de autenticación. En el ejemplo he puesto una de las webs de autenticación que usa Facebook. En esa web, el usuario puede permitirnos el acceso a su cuenta. Si funciona correctamente, la web nos redirigirá a una URL de respuesta configurada en el servicio al registrar nuestra aplicación. En esa redirección, suele enviarse como parámetro el token de acceso a la API. Y listo, ya podemos realizar peticiones autenticadas con el token que hemos recibido.

¿Como implementamos esto antes de Windows Phone 8.1?

Pues muy a “mano”. Básicamente, siguiendo los siguientes pasos:

  • Construías en nuestra aplicación una página que contuviese un WebBrowser.
  • Si no estamos autenticados (no tenemos un token) navegar a la URL de OAuth en esa página
  • Vigilar los eventos de navegación del WebBrowser para detectar cuando esta redirigiéndonos a la respuesta.
  • Procesar la URL de respuesta para extraer el token.

No es que sea el proceso más complicado del mundo, pero es todo muy manual y puede llevarnos un rato de prueba/error si queremos que funcione con varios proveedores distintos al mismo tiempo.

¿Como implementamos esto ahora en Windows Phone 8.1?

Lo implementamos usando el WebAuthenticationBroker, que nos facilita la vida:

  • Si no estamos autenticados (no tenemos un token) llamamos al método AuthenticateAndContinue de la clase WebAuthenticationBroker.
  • Recibimos la respuesta y extraemos el token.

Si, ya está. Solo tenemos que hacer eso. El propio WebAuthenticationBroker se encarga por nosotros de todos los demás pasos. Esta fue una de las grandes novedades que incluyó Windows 8 en su API WinRT cuando salió y por fin la tenemos disponible en Windows Phone. No obstante existen ciertas diferencias entre el API de Windows 8 y la de Windows Phone 8.1, como veremos a continuación.

WebAuthenticationBroker: Windows Store vs Windows Phone

Como hemos dicho, solo tenemos que llamar al método AuthenticateAndContinue de la clase WebAuthenticationBroker, pero este método no existe en Windows Store, donde usaremos en su lugar AuthenticateAsync. Esta diferencia, que encontraremos en algunas APIs más de Windows Phone 8.1, va mas allá de un simple cambio de nombre. AuthenticateAsync es, como su nombre indica asíncrono, podemos usar await para esperar que se complete y nos de el resultado. Por el contrario, AuthenticateAndContinue no es asíncrono y devuelve ¡VOID!, ahora veremos porqué y como obtener el resultado.

El problema principal es el siguiente. En terminales de baja memoria, 512Mb, Windows Phone no puede asegurar en todo momento que pueda mantener nuestra aplicación abierta al mismo tiempo que lanza otra aplicación, la cual se encargará de realizar la autenticación. Por este motivo, ciertas APIs que necesitan abrir un “Broker”, una aplicación del sistema para realizar una acción, como el WebAuthenticationBroker, han implementado un método llamado “DoSomethingAndContinue” que no devuelve ningún resultado. En su lugar seguiremos el siguiente flujo:

image

Básicamente tenemos los siguientes pasos:

  1. Nuestra aplicación ejecuta el método AuthenticateAndContinue del WebAuthenticationBroker. En esta
  2. La aplicación WebAuhtenticationBroker del sistema pasa a primer plano y nuestra app se suspende. Dependerá del sistema si se conserva en memoria o no.
  3. El usuario realiza las acciones necesarias y el WebAuthenticationBroker termina, activando nuestra app de nuevo.
  4. Nuestra app pasa al primer plano, recibiendo como argumento un objeto de tipo AuthenticationResult.
  5. Tenemos que enviar la respuesta a nuestra página/viewmodel para seguir trabajando.

Viendo el código.

Ahora que tenemos claro como funciona el proceso, vamos a ver el código implicado en él. Para el primer paso, necesitaremos una URL de autenticación OAuth que podamos usar. En este ejemplo vamos a usar una de Facebook. Para obtener una URL, tendremos que ir a https://developers.facebook.com/, registrarnos y crear una nueva app en el menú superior “Apps”:

image

Una vez creada, nos mostrará la página de la app con el AppID y el AppSecret, estos identificadores serán necesarios para componer nuestra URL de conexión a continuación:

https://www.facebook.com/dialog/oauth?client_id=[APPID]&redirect_uri=http://localhost/reply&scope=[PERMISOS]&display=popup&response_type=token

Simplemente tenemos que sustituir el texto [APPID] por el appID que nos dio Facebook al registrar la aplicación y añadir los permisos necesarios, según las acciones que deseemos realizar.

El código sería algo como esto:

AuthenticateAndContinue
private void LoginFacebookExecute()
{
    string appID = «YOUR APP ID FROM FACEBOOK»;
    string permissions = «publish_actions»;
    string authUrl = string.Format(«https://www.facebook.com/dialog/oauth?client_id={0}&redirect_uri=http://localhost/reply&scope={1}&display=popup&response_type=token», appID, permissions);
            
    WebAuthenticationBroker.AuthenticateAndContinue(new Uri(authUrl), new Uri(«http://localhost/reply»), null, WebAuthenticationOptions.None);
}

Como vemos no es un código complicado. formamos la URL de OAuth2 de Facebook añadiendo nuestro APPID y los permisos a usar y a continuación llamamos al método AuthenticateAndContinue. Es en esta parte donde viene lo divertido. Justo tras llamar a ese método, nuestra aplicación se suspende y se abre el WebAuthenticationBroker. ¿Y como obtenemos el resultado de la operación? Bien, controlando el método OnActivated de la clase App (App.xaml.cs) Desde ese método deberemos pasar la información a nuestra ViewModel. Para hacer esto más sencillo, yo he creado un Interface que añado a todas las ViewModels que hacen uso de métodos “…AndContinue”. Esta interface se llama IContinuationAwareViewModel y define el método Continue:

IContinuationAwareViewModel
public interface IContinuationAwareViewModel
{
    void Continue(IActivatedEventArgs args);
}

Simplemente la implemento en la ViewModel donde hemos llamado a AuthenticateAndContinue y dentro del método Continue pongo el código para recibir y procesar la respuesta de Facebook:

Continue
public void Continue(IActivatedEventArgs args)
{
    var arguments = (WebAuthenticationBrokerContinuationEventArgs)args;
    WebAuthenticationResult result = arguments.WebAuthenticationResult;

    if (result.ResponseStatus == WebAuthenticationStatus.Success)
    {
        string responseCode = result.ResponseData;
        responseCode = responseCode.Substring(responseCode.IndexOf(«=») + 1);
        AccessToken = responseCode.Split(‘&’).First();
        ExpirationTime = int.Parse(responseCode.Split(‘&’).Last().Split(‘=’).Last());
    }
}

Comprobamos si la operación a tenido éxito y simplemente procesamos la cadena de texto que devuelve Facebook con el token de acceso y el tiempo de expiración en segundos.

Ahora ya solo nos queda ver como invocar a este método desde el OnActivated de la clase App:

App OnActivated
protected override void OnActivated(IActivatedEventArgs args)
{
    var rootFrame = (Frame)Window.Current.Content;
    var currentPage = (Page)rootFrame.Content;
    var currentViewModel = (IContinuationAwareViewModel)currentPage.DataContext;

    currentViewModel.Continue(args);
}

Primero obtenemos el frame actual de la aplicación, del cual extraemos la página activa. Del DataContext de la página extraemos la ViewModel (que convertimos a IContinuationAwareViewModel) y ya solo nos queda invocar al método Continue pasando los argumentos de activación. Es tarea del método Continue implementado en la ViewModel decidir como usar esos argumentos y que información obtener. De esta forma, si tenemos varias páginas que usen métodos “…AndContinue” el método de activación será standard para todas ellas.

Y con esto llegamos al final de esta artículo. Como siempre, aquí tienes el ejemplo funcionando con el código que hemos visto, para que puedas jugar con él y por supuesto usando MVVM para que veas como implementar WebAuthenticationBroker con todas las piezas en su sitio.

Espero que lo disfrutes.

Un saludo y Happy Coding!

 

 

[Windows Phone] Este viernes 16 de mayo llega //Publish

Hola a todos!

Después de mucho tiempo de preparación, ya está aquí el 16 de mayo y el evento //Publish que se celebrará a nivel mundial en más de 60 ciudades al mismo tiempo.

En Madrid, las inscripciones ya están cerradas y tenemos todo preparado para pasar un gran día juntos, desarrollando apps y con muchas sorpresas.

El día empezará a las 9 de la mañana con el registro general. Según vayáis llegando, empezaréis a desarrollar. Hemos decidido no hacer charlas técnicas ese día. Estaremos varios por allí para ayudaros con lo que necesitéis, pero el objetivo es desarrollar y no queremos distraeros. a la 1 de la tarde pararemos una hora para comer y luego seguiremos hasta las 6 y media de la tarde desarrollando. A las 6:30 pararemos, para que cada cual presente sus apps a los demás y el jurado, compuesto por Javier Suarez Ruiz, Santiago Porras y Alejandro Campos, deliberará sobre las mejores apps. Entre ellas escogeremos dos: La primera podrá escoger como premio entre un Lumia 1520 y una tablet Dell Venue 8 Pro. El premio restante será para el segundo. Pero no os preocupéis que tendremos sorpresas y regalos parar todos!!.

¿Vas a venir? ¿Qué tienes que traer para poder aprovechar bien el día?

  • Lo principal: muchas ganas de desarrollar, aprender y sacar una app al público.
  • Como solo tenemos un día, lo ideal es que ya traigas algo desarrollado de casa, pero si vienes con una idea, haremos lo posible para que te vayas con mucho hecho y funcionando… incluso puede que con la aplicación publicada en la tienda.
  • Recuerda traer tu portatil, con el software necesario instalado. Si tienes que instalarlo sobre la marcha te ayudaremos, pero perderas un valioso tiempo instalando. Necesitarás al menos:
    • Windows 8.1 Pro o superior de 64 bits
    • SDK de Windows Phone 8.1

Si tu idea es desarrollar una app Windows Phone 8.1, tendremos varios terminales para que la puedas probar (un Lumia 1520 y un Lumia 625 listos con Windows Phone 8.1).

Para ayudarte, tendrás un monton de gente que controla de Windows Phone:

  • Javier Suarez Ruiz
  • Santiago Porras
  • Alejandro Campos
  • Un servidor

Además, Santiago llegará al evento con la gorra y bufanda de diseñador, listo para daros un apoyo en el diseño de vuestra app para sacarle el máximo partido y que tenga la mejor apariencia posible.

Por último, recordaros que el evento se celebrará en las oficinas de Microsoft Ibérica:

 

Asignar imagen

 

Paseo Club Deportivo, número 1.

Centro Empresarial La Finca.

Un saludo y Happy Coding!

 

[Windows Phone 8.1] MVVM en apps universales.

Hola a todos!

Una de las grandes novedades, como ya vimos anteriormente, en la nueva versión de Windows Phone 8.1 son las aplicaciones universales. Este nuevo tipo de proyecto nos promete ser capaces de compartir la gran mayoría de código entre una versión Windows Store y otra Windows Phone de la misma aplicación. ¿Pero realmente es así? Antes de empezar a repasar nuevas APIs, XAML y otras cosas, creo que es importante ver como podemos usar MVVM en nuestras aplicaciones universales para compartir gran parte del código.

Implementando MVVM en proyectos universales

Realmente la implementación de MVVM no cambia en absoluto, con respecto a la que podríamos hacer en Windows Phone 8.0 o Windows Store. Lo único que cambia es el proyecto donde colocamos nuestros archivos.

Mientras que anteriormente implementábamos MVVM en el propio proyecto de la aplicación o una PCL, en las apps universales usaremos el proyecto Shared para almacenar nuestros archivos. El objetivo es llegar a tener solo el XAML de las páginas en cada proyecto de plataforma y que toda la lógica de la aplicación esté centralizada en el proyecto Shared. ¿Es esto posible? Si en la mayoría de los casos. Siempre nos encontraremos con casos en que las APIs de Phone y Store no son exactamente iguales, incluso donde su valor de retorno no es el mismo. En estos casos tendremos dos opciones: Crear una ViewModel específica para cada proyecto o usar bloques condicionales de compilación. ¿Cual usar en cada caso? Pues dependerá un poco de nuestras necesidades particulares en cada momento y de lo que necesitemos hacer. Si es poco el código particular de cada plataforma y mucho el código compartido, quizás usar un bloque condicional nos ayude a compartir código y no tener que reescribirlo todo. Sin embargo, si el código particular es la mayoría de la ViewModel, quizás sea mejor crear una por cada plataforma.

Vamos a comenzar por las bases. En todo proyecto XAML con MVVM, me gusta crear dos clases base: PageBase y ViewModelBase.

PageBase

PageBase la usaré como clase base de todas mis páginas. Esto me permite varias cosas:

  • Definir comportamientos comunes a todas las páginas, como detección de internet.
  • Definición de transiciones comunes.
  • En conjunto con la ViewModelBase, “rutear” los metodos de navegación hacia las ViewModels.
  • Establecer en la ViewModelBase el Frame activo de cada página, de forma que sea más facilmente accesible.

Con esta funcionalidad, la clase PageBase tendría este aspecto:

PageBase
public class PageBase : Page
{
    private ViewModelBase vm;

    public PageBase()
    {
    }

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);

        vm = (ViewModelBase)this.DataContext;
        vm.SetAppFrame(this.Frame);
        vm.OnNavigatedTo(e);
    }

    protected override void OnNavigatedFrom(NavigationEventArgs e)
    {
        base.OnNavigatedFrom(e);
        vm.OnNavigatedFrom(e);
    }

    protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
    {
        base.OnNavigatingFrom(e);
        vm.OnNavigatingFrom(e);
    }
}

Aquí podemos observar una de las ventajas de Windows Phone 8.1 y las aplicaciones universales. Ya no tenemos un objeto PhoneApplicationPage. Ahora todas las páginas, tanto de Windows Phone como Windows Store, heredan del objeto Page. Esto permite que de igual forma, nuestra página base pueda ser compartida entre las dos plataformas.

Podéis ver que el código no es nada de otro mundo, controlamos los métodos de navegación y en el método OnNavigateTo obtenemos la ViewModel asignada a la página y establecemos el Frame activo en la misma. Por último en todos los métodos de navegación invocamos un método que se llama igual en la ViewModelBase. De esta forma no necesitamos usar code behind para controlar la navegación de nuestras páginas.

ViewModelBase

Nuestra ViewModelBase actuará como la clase base de las cuales heredarán todas nuestras ViewModels, lo que nos permitirá darles una funcionalidad básica y homogénea a todas:

  • Acceso al objeto Frame de la página asociada.
  • Acceso a los eventos de navegación para sobre escribirlos.
  • Notificación de cambios.
  • Notificación de carga a la UI.

El código de la ViewModelBase, sería parecido a este:

ViewModelBase
public abstract class ViewModelBase : INotifyPropertyChanged
{
    private Frame appFrame;
    private bool isBusy;

    public ViewModelBase()
    {
    }

    public Frame AppFrame
    {
        get { return appFrame; }
    }

    public bool IsBusy
    {
        get { return isBusy; }
        set
        {
            isBusy = value;
            RaisePropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public abstract Task OnNavigatedFrom(NavigationEventArgs args);

    public abstract Task OnNavigatingFrom(NavigatingCancelEventArgs args);

    public abstract Task OnNavigatedTo(NavigationEventArgs args);

    public void RaisePropertyChanged([CallerMemberName]string propertyName = «»)
    {
        var Handler = PropertyChanged;
        if (Handler != null)
            Handler(this, new PropertyChangedEventArgs(propertyName));
    }

    internal void SetAppFrame(Frame viewFrame)
    {
        appFrame = viewFrame;
    }
}

Hemos creado tres métodos abstractos: OnNavigatedFrom, OnNavigatingFrom y OnNavigatedTo que implementaremos en nuestras ViewModels para poder ejecutar código durante la navegación. Esto es muy útil cuando queremos recibir un parámetro de otra página, pero también al cargar datos. Si realizamos carga de datos en el constructor, podemos ralentizar la carga de la página. Sin embargo usando el método OnNavigatedTo, realizamos la carga una vez que la página está activa, no antes.

Ahora ya podemos empezar a crear nuestras páginas y ViewModels, usando las clases base que hemos definido.

Páginas

En cada página, tendremos que incluir el namespace de nuestra página base y cambiar su tipo, tanto en XAML como en C#:

 

MainPage.xaml
<base:PageBase
    x:Class=«Wp81MVVM.MainPage»
    xmlns:base=«using:Wp81MVVM.Base»
    xmlns=«http://schemas.microsoft.com/winfx/2006/xaml/presentation»
    xmlns:x=«http://schemas.microsoft.com/winfx/2006/xaml»
    xmlns:local=«using:Wp81MVVM»
    xmlns:d=«http://schemas.microsoft.com/expression/blend/2008»
    xmlns:mc=«http://schemas.openxmlformats.org/markup-compatibility/2006»
    mc:Ignorable=«d»>

    <Grid Background=»{ThemeResource ApplicationPageBackgroundThemeBrush}«>

    </Grid>
</base:PageBase>

 

 

MainPage.xaml.cs
namespace Wp81MVVM
{
    using Wp81MVVM.Base;

    public sealed partial class MainPage : PageBase
    {
        public MainPage()
        {
            this.InitializeComponent();
        }
    }
}

 

Ahora solo tenemos que definir una ViewModel para esta página, implementando la ViewModelBase y sus métodos abstractos de navegación:

ViewModel
public class MainViewModel : ViewModelBase
{
    public MainViewModel()
    {

    }

    public override Task OnNavigatedTo(Windows.UI.Xaml.Navigation.NavigationEventArgs args)
    {
        return null;
    }

    public override Task OnNavigatedFrom(Windows.UI.Xaml.Navigation.NavigationEventArgs args)
    {
        return null;
    }

    public override Task OnNavigatingFrom(Windows.UI.Xaml.Navigation.NavigatingCancelEventArgs args)
    {
        return null;
    }
}

Ya solo nos queda unir nuestra página y nuestra ViewModel, de la forma que más nos guste: usando IoC, asignándola directamente en el constructor de la página… En este caso voy a usar Unity para resolver nuestra ViewModel y servicios. Para ello, lo primero que necesitaremos es añadir una referencia en nuestro proyecto universal a Unity. En este tipo de proyectos esto significa añadir la referencia a cada proyecto de plataforma (Phone y Store). Vamos a comenzar por el proyecto Store. Solo tenemos que hacer click derecho sobre el nodo “References” del proyecto y seleccionar la opción “Manage NuGet packages”, buscar “Unity” y presionar el botón instalar:

image

Ahora deberíamos repetir lo mismo con el proyecto Phone, pero el resultado será el siguiente:

image

El problema aquí es que, en la mayoría de los casos, todavía no se han actualizado los paquetes de NuGet para soportar los tipos de proyecto “WindowsPhoneApp, version=8.1”. ¿Quiere decir esto que no podemos usar Unity? Ni mucho menos. Lo unico que quiere decir es que no podemos instalarlo desde NuGet. Como Windows Phone 8.1 y Windows Store comparten ahora todo el core de desarrollo, “en teoría” podríamos usar el mismo ensamblado que en Windows Store. Solo tenemos que hacer click con el botón derecho sobre “References” en el proyecto Windows Phone y seleccionar “Add Reference”, presionar el botón “Browse” e ir a la carpeta de packages donde se ha descargado Unity para Windows Store previamente, seleccionando la carpeta NetCore45, que es la usada en Windows Store, seleccionamos la dll dentro de esa carpeta y presionamos “add” y “ok” y listo, ya tendremos Unity funcionando en nuestra aplicación Windows Phone 8.1.

Ahora en nuestro proyecto Shared, en la carpeta Base de ViewModels, vamos a añadir una nueva clase llamada ViewModelLocator, que haga uso de Unity para registrar y resolver nuestras ViewModels, exponiéndolas mediante propiedades públicas:

ViewModelLocator
public class ViewModelLocator
{
    IUnityContainer container;

    public ViewModelLocator()
    {
        container = new UnityContainer();

        container.RegisterType<MainViewModel>();
    }

    public MainViewModel MainViewModel
    {
        get { return container.Resolve<MainViewModel>(); }
    }
}

Como podemos ver, desde nuestro proyecto Shared podemos acceder a cualquier ensamblado referenciado en nuestros proyectos de plataforma, haciendo muy sencillo escribir código compartido. Ya solo nos queda añadir nuestro ViewModelLocator como una referencia en el archivo App.xaml, que también se encuentra compartido en el proyecto Shared:

Shared App.xaml
<Application
    x:Class=«Wp81MVVM.App»
    xmlns=«http://schemas.microsoft.com/winfx/2006/xaml/presentation»
    xmlns:x=«http://schemas.microsoft.com/winfx/2006/xaml»
    xmlns:local=«using:Wp81MVVM»
    xmlns:VMBase=«using:Wp81MVVM.Base»>

    <Application.Resources>
        <VMBase:ViewModelLocator x:Key=«Locator»/>
    </Application.Resources>
</Application>

Y ya lo podemos usar en las páginas de ambas plataformas. De la misma forma que haríamos en un proyecto de Phone o Store tradicional:

 

MainPage.xaml Windows Store
<base:PageBase
    x:Class=«Wp81MVVM.MainPage»
    xmlns:base=«using:Wp81MVVM.Base»
    xmlns=«http://schemas.microsoft.com/winfx/2006/xaml/presentation»
    xmlns:x=«http://schemas.microsoft.com/winfx/2006/xaml»
    xmlns:local=«using:Wp81MVVM»
    xmlns:d=«http://schemas.microsoft.com/expression/blend/2008»
    xmlns:mc=«http://schemas.openxmlformats.org/markup-compatibility/2006»
    mc:Ignorable=«d»
    DataContext=»{Binding MainViewModel, Source={StaticResource Locator}}«>

    <Grid Background=»{ThemeResource ApplicationPageBackgroundThemeBrush}«>

    </Grid>
</base:PageBase>

 

 

 

Mainpage.xaml Windows Phone
<base:PageBase
    x:Class=«Wp81MVVM.MainPage»
    xmlns:base=«using:Wp81MVVM.Base»
    xmlns=«http://schemas.microsoft.com/winfx/2006/xaml/presentation»
    xmlns:x=«http://schemas.microsoft.com/winfx/2006/xaml»
    xmlns:local=«using:Wp81MVVM»
    xmlns:d=«http://schemas.microsoft.com/expression/blend/2008»
    xmlns:mc=«http://schemas.openxmlformats.org/markup-compatibility/2006»
    mc:Ignorable=«d»
    Background=»{ThemeResource ApplicationPageBackgroundThemeBrush}«
    DataContext=»{Binding MainViewModel, Source={StaticResource Locator}}«>

    <Grid>

    </Grid>
</base:PageBase>

 

En este punto, puede parecer que tener una sola página es mejor y compartirla en el proyecto Shared. Si, podríamos hacerlo sin ninguna dificultad. Pero en la mayoría de los casos, haría que en Phone o Store, la UX fuese horrible. En mi caso soy un firme defensor de hacer una interface de usuario para cada plataforma, aprovechándonos de sus puntos fuertes. Sin embargo, si que es posible que nos encontremos compartiendo pequeños trozos de interface en forma de controles de usuario y en muchos casos usando las diferentes páginas solo para modificar la distribución de la información en pantalla para aprovechar mejor el área de trabajo de cada plataforma. Esto da para un próximo artículo.

Conclusión

Esto es todo por hoy, como hemos podido ver es muy fácil compartir código con los proyectos universales, sin necesidad de hacks ni cosas extrañas (seguro que en algún momento nos hacen falta jeje) y nos permite construir apps para la plataforma Windows en conjunto. Como siempre, podéis descargar todo el código de ejemplo aquí para jugar con él y usarlo como punto de partida para vuestras apps.

Sería un buen arranque para una app que queráis presentar en el Hackathon //Publish del 16 de Mayo en Madrid, Barcelona o Palma de Mayorca. Premios, asistencia para el diseño de tu app, y mentores para ayudarte a crear el próximo hit!

Un saludo y Happy Coding!

 

[Eventos] Después del //Build/ llega //Learn/ y //Publish/

Hola a todos!

Solo hace unos días que termino el //Build/ 2014. Este año los seguidores de Windows Phone tuvimos grandes novedades y anuncios con la presentación de Windows Phone 8.1. Desde Microsoft Corp. y la comunidad de MVPs de Windows Phone, queremos ayudarte a seguir el ritmo de las novedades y crear grandes aplicaciones usando las nuevas ventajas que ofrece la plataforma Windows con esta última revisión.

Para ello, se han creado dos eventos que tendrán lugar en Abril y Mayo: //Learn/ y //Publish/

//Learn/

Este evento online está organizado directamente por los MVPs de Windows Phone. Durante 6 horas, tendremos webcast sobre diferentes temáticas de Windows Phone 8.1: aplicaciones universales, diseño, nuevas APIs, notificaciones… Lo mejor de todo, es que no solo será en Inglés. Dispondremos de una track principal en inglés y tracks paralelas en Chino, Ruso, Portugués, Frances y Español!!

En la Track en Español, Sorey García, Roberto Alvarado, Jose Luis Latorre, Ivan Toledo y un servidor estaremos dando todo el contenido. Las sesiones que tendremos serán las siguientes (Puede variar alguna todavía):

  • Introducción a Windows Phone 8.1
  • Empezando a construir apps Windows XAML
  • Controles de layout y transiciones de páginas
  • Adaptando tu UI a diferentes pantallas
  • Ciclo de vida de apps WinRT XAML
  • Tiles, badges, notificaciones y el Action center
  • Tareas en background
  • Windows XAML para desarrolladores Silverlight

El evento se celebrará el 24 de Abril, se pueden registrar aquí. Al ser un evento internacional los horarios han tenido que ser consensuados y España no sale demasiado bien parada. El evento en España empezará alrededor de la 1 de la mañana del día 25… pero no os preocupéis, el material será grabado y al día siguiente, o tan pronto tenga los enlaces, los pondré aquí.

//Publish/

Cerca de un mes después del evento //Learn/ tendremos un nuevo evento, esta vez presencial. Se trata de un hackathon organizado entre Microsoft y la comunidad MVP. En él ayudaremos a los asistentes a crear apps para Windows 8.1 y Windows Phone 8.1, tendremos mentores, premios, dispositivos para probar vuestras apps y os invitaremos a comer.

En España tenemos la suerte de tener tres sedes: Barcelona, organizada por Microsoft y Madrid y Palma de Mallorca, organizadas por la comunidad MVP. En mi caso estaré en Madrid, junto con Javier Suarez y Santiago Porras para ayudaros a crear apps increíbles y publicarlas. El evento en Madrid se llevará a cabo en las oficinas de Microsoft el día 16 de mayo.

En breve tendremos más información, según vayamos avanzando con la organización y actualizaré este post con todas las novedades. Por ahora podéis registraros en cualquiera de las tres sedes aquí.

Estos eventos son grandes oportunidades para actualizar vuestros conocimientos o introduciros en la plataforma Windows, así que no perdáis esta oportunidad. Nos vemos en breve.

Un saludo y Happy Coding!

[Windows Phone 8.1] Opciones para desarrollar

Hola a todos!

En el artículo anterior, hablamos sobre las novedades de Windows Phone 8.1 en cuanto a las herramientas que tenemos disponibles. Hoy vamos a hablar sobre las nuevas opciones y frameworks que tenemos disponibles para crear nuestras aplicaciones.

Bien, esta es una de las cosas que mas enrolladas están. Windows Phone 8.1 trae consigo nuevas formas de hacer las cosas, pero Microsoft no ha querido dejar a nadie en la cuneta, con lo que es totalmente compatible con el código que ya teníamos para Windows Phone 8.0.

En primer lugar tenemos que tener en cuenta que el motor de ejecución de apps ha cambiado en Windows Phone 8.1. Se ha abandonado el motor basado en Silverlight y se ha creado todo un nuevo motor de ejecución basado en WinRT y Windows Store. Pero sobre este motor, se ha trabajado para poder ejecutar las aplicaciones de Windows phone 8.0 sin necesidad de realizar ningún cambio ni adaptarlas. Automáticamente todas son compatibles. Con esto, podemos desarrollar de las siguientes formas:

  • Silverlight para Windows Phone 8.0: Podemos crear una app de Windows Phone 8.0 y se ejecutará perfectamente en terminales 8.0 y 8.1. Pero no tendremos acceso a las nuevas APIs de Windows Phone 8.1.
  • Silverlight para Windows Phone 8.1: Esta nueva versión nos permite migrar una app Windows Phone 8.0 de forma muy rápida (con una opción de menú) y además acceder a las nuevas APIs de Windows Phone 8.1.
  • Windows XAML: Es la gran novedad de Windows Phone 8.1, básicamente es el mismo sistema usado en las apps Windows Store XAML. 100% WinRT y mismo XAML para la interface de usuario. Es el que más cambia con respecto a la anterior versión del sistema. Con Windows XAML podremos crear proyectos universales, de los que hablaremos más adelante, que nos permitirán desarrollar para Windows Phone y Windows Store de forma muy sencilla.
  • WinJS: Para todos los aficionados a HTML5, JS y CSS… ahora podréis desarrollar apps Windows Phone nativas de la misma forma que ya se hacía en Windows Store usando HTML5 y JS. Con WinJS también podréis realizar proyectos universales. Cabe mencionar que, aunque usemos la denominación WinJS, en realidad estamos hablando de HTML5 y JS nativo, con lo que podrás usar librerías como JQuery, Angular, Knockout… WinJS es solo necesario para acceder a funcionalidades del sistema.

El nuevo camino planteado por Microsoft es Windows XAML / WinJS. Silverlight para Windows Phone 8.1 ha sido pensado para escenarios muy concretos. En particular la mayor fortaleza de Silverlight es permitirte migrar tus desarrollos de Windows Phone 8.0 a 8.1 y conseguir acceso a las nuevas APIs sin tener que reescribir toda la aplicación o gran parte de ella.

De echo, las aplicaciones de correo, alarmas, calendario, etc… que vienen en el sistema están escritas con este mismo framework Windows XAML. Con lo que nos podemos hacer una idea de su potencia dandole un vistazo a las mismas. Se ha reescrito el motor de ejecución de aplicaciones para Windows XAML y se ha creado una superficie compatible con Silverlight que permite la ejecución de las nuevas aplicaciones de Silverlight 8.1 en el motor de Windows XAML. De esta forma es como las apps  de Silverlight 8.1 pueden acceder a las nuevas APIs de Windows XAML.

image

Como podemos ver, nuestras apps de Windows Phone 8 se seguirán ejecutando sobre el mismo motor, por lo que no tendremos problemas de compatibilidad. Las apps Silverlight 8.1 se ejecutarán sobre una superficie de compatibilidad sobre el motor de ejecución Windows XAML, por eso tienen acceso a todas las nuevas APIs (nuestras apps wp8 no podrán acceder a las nuevas APIs ni usando reflection siquiera). Las nuevas aplicaciones Windows XAML se ejecutan directamente sobre su nuevo motor.

Pero cada sistema tiene sus pros y sus contras. Windows XAML es una nueva manera de desarrollar traída directamente de las aplicaciones Windows Store e introduce muchos cambios. Así, echaremos en falta los ya tan típicos Launchers y Choosers de Windows Phone, que no existen en Windows XAML y algunas cosas más. ¿Como decidimos entre uno u otro para nuestros desarrollos? Aquí intento dejaros una lista de cosas a valorar. La más importante no obstante es recordar que Silverlight para Windows Phone 8.1 existe como ayuda en la transición a la nueva versión del sistema. La opción de continuidad en el futuro es Windows XAML. No incluimos Silverlight para Windows Phone 8 en este apartado, porque no tienes que hacer nada, por defecto tu aplicación funcionará en Windows Phone 8.1.

  • Silverlight para Windows Phone 8.1:
    • Parto de una aplicación para Windows Phone 8.0.
    • No estoy interesado en hacer una versión para Windows Store.
    • Quiero poder tener acceso a las nuevas APIs de Windows Phone 8.1.
    • Necesito hacer uso de Launchers y Choosers en mi aplicación.
    • Mi aplicación usa como característica importante el acceso a la pantalla de bloqueo.
  • Windows XAML:
    • Parto de una aplicación Windows Store.
    • No parto de una aplicación Windows Store o Windows Phone, empiezo desde 0.
    • Tengo una aplicación para Windows Phone 8.0 pero no hago uso de Launchers y Choosers o la pantalla de bloqueo.
    • Quiero poder tener un proyecto único para mi aplicación Phone y Store, de forma que sea muy sencillo mantener ambas aplicaciones.
  • WinJS:
    • Tengo una aplicación WinJS para Windows Store.

Como podemos ver, para cada uno la situación puede ser distinta y el camino a escoger también. Me gusta que Microsoft haya tenido en cuenta el ofrecer una vía rápida de migración de Windows Phone 8.0 a 8.1, mediante Silverlight. Pero debemos tener en cuenta que se trata de eso, una vía de migración. En mi opinión, si vamos a desarrollar una aplicación nueva deberíamos decantarnos por Windows Xaml / WinJS (según nuestra preferencia de lenguaje) y plantearnos seriamente usar los nuevos tipos de proyectos “Universales” que nos permiten desarrollar para Store y Phone al mismo tiempo. Pero, como ya mencionamos antes, Windows XAML trae consigo muchas APIs nuevas y otras muchas que han desaparecido. ¿Qué APIs vamos a perder en comparación con Silverlight y que alternativas tenemos? Vamos a intentar ponerlas en común:

API Silverlight API Windows XAML Notas
PhotoChooserTask y CameraCaptureTask FileOpenPicker Cuando al FileOpenPicker le añadimos un filtro de archivo de imágenes, muestra un botón para acceder a la cámara, además de permitirnos seleccionar una o varias imágenes del teléfono.
Maps/Call/Mail/Marketplace LaunchUri Muchos Launchers y Choosers se pueden cambiar por Uris estandard.
IconicTile / CycleTile, FlipTile Windows 8.1 tiles Ahora los tiles en Windows Phone 8.1 son los mismos que en Windows Store, por lo que los tres tipos de 8.0 desaparecen, podemos elegir entre cerca de 60 plantillas.
Scheduled Background agent Background Task Las tareas en background pasan a ser las usadas en Windows Store.
MPNS WNS Las notificaciones push dejan de usar el sistema Microsoft Push Notification Service para acoger el Windows Notification Service, de Windows Store.
Share Tasks Share Contract En Windows Phone 8.1 tenemos el mismo contrato de compartir que ya teníamos en Windows Store.
Panorama control Hub control El control panorama desaparece y es sustituido por el control Hub de Windows Store, se mantiene el control Pivot.
LongListSelector GridView/ListView/SemanticZoom Se cambia el control LongListSelector por los Grid/ListView con SemanticZoom.

También hay APIs que desaparecen sin alternativa:

  • Lockscreen, en Windows XAML no tendremos acceso a las APIs para establecer nuestra aplicación como proveedor de la imagen de la pantalla de bloqueo.
  • FMRadio, en Windows XAML no tendremos acceso al API de radio FM.
  • Globalization, se usará el sistema de globalización de Windows Store, por lo que este namespace entero desaparece.
  • Voip, no existe en Windows XAML.
  • Alarm/PeriodicTask/ScheduledAction, no existe en Windows XAML.
  • RadialGradientBrush, no existe en Windows XAML.

Tendremos que tener estas listas en cuenta. Si nuestra aplicación necesita alguna de estas APIs, deberemos usar Silverlight para Windows Phone 8.1.

Pero no todo son pérdidas. También tendremos muchas nuevas APIs que nos brindarán mucha más potencia para nuestros desarrollos:

  • Acceso a la galería de imágenes/videos/documentos y música. Mediante el uso de FileOpenPicker podremos acceder a todos los documentos y archivos multimedia de nuestro dispositivo sin restricciones!
  • APIs criptográficas, para poder leer y trabajar con PKIs, certificados  X509 y soporte de métodos criptográficos estandard.
  • Nueva ApplicationBar, extraida directamente de Windows 8.1, enlazable a datos y con muchas nuevas funcionalidades.
  • Nuevos controles: FlipView, GridView, ListView, SemanticZoom, Menu flyouts, RichTextBox, Hub…
  • Nuevo API MediaPlayer para reproducción en background de audio.
  • Namespace Windows.Media.Editing para ayudarnos a editar video directamente en nuestra aplicación.
  • Nuevas funcionalidades de captura de la pantalla de nuestra aplicación para poder grabar videos de la misma usando el namespace Windows.Media.Capture.
  • Transferencias en background mejoradas.
  • Nuevos tiles.
  • Capacidades de Geofencing, que nos permitirán disparar ejecución de código en segundo plano basado en posicionamiento.
  • NFC: mejor soporte de TAGS, TAGS de solo lectura, escribir TAGS sin formato.
  • Control WebView mejorado (el mismo que en Windows Store).
  • Se suprime el IsolatedStorage completamente para dar paso a la api de Storage de Windows Store.
  • Roaming de settings.
  • Contrato de compartir.
  • Soporte de lectura/escritura en tarjetas SD.
  • Nuevas APIs de notificaciones y Action Center.
  • Integración de DirectX y XAML.
  • WebAuthenticationBroker.

Como podemos ver, muchas y variadas novedades. No obstante una de las novedades, en cuanto a desarrollo, que más resonará es la convergencia de la plataforma. Ya lo hemos mencionado en este artículo varias veces. Con Windows XAML tendremos a nuestra disposición nuevos proyectos que nos permitirán crear aplicaciones para Windows Store y Windows Phone. Lo veremos en el siguiente artículo.

Un saludo y Happy coding!