[Universal Apps] Navegación entre páginas, paso de parámetros y gestión de la tecla volver (2/2)

Introducción

Anteriormente vimos como como se realiza la navegación entre páginas
en Windows Phone 8.1 además de aprender como gestionar la tecla física
atrás. En el artículo actual pasaremos a aplicar y utilizar los
conceptos básicos previos tal y como lo utilizaríamos en una aplicación
real. Vamos a aprender a navegar utilizando un servicio de navegación e
incluso

MVVM en escena!

Realmente podemos mantener una implementación MVVM
muy similar a como hacíamos hasta ahora en Windows Phone 8. Comenzamos
por la base. Contamos con dos ficheros clave en nuestro proyecto
Universal para implementar el patrón MVVM:

  • PageBase
  • ViewModelBase

PageBase

Como revelamos con su nombre, será una clase de la que heredaran
todas las páginas de nuestra aplicación. Y si, comentamos que serán
todas las páginas de la aplicación (ya sean del proyecto Windows o del
proyecto Windows Phone). Las páginas en ambas plataformas es exactamente
igual, un objeto de tipo Page. Esta clase cuenta con varios objetivos:

  • Establecer el Frame activo en todo momento para que el acceso al mismo sea sencillo.
  • Permitir el acceso de los eventos de navegación desde nuestras viewmodels.

Además podría interesarnos además:

  • Gestionar las transiciones entre páginas.
  • Gestionar estados (Loading, etc.)
  • Gestionar el estado segun la conexión de red.

Con la funcionalidad básica (facilitarnos el acceso a Frame y eventos de navegación) quedaría:

public class PageBase : Page
{
     private ViewModelBase _vm;
 
     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);
     }
}

Gestionamos los eventos básicos de navegación (al entrar y al salir
de la página) de modo que, en el método OnNavigateTo obtenemos la
viewmodel de la página y asignamos el Frame.

ViewModelBase

Continuamos con la segunda de nuestras clases base. En esta ocasión
trataremos la clase base de la que heredarán todos los viewmodels. Los
objetivos básicos de la clase son:

  • Notificar cambios (implementar INotifyPropertyChanged).
  • Acceso al objeto Frame que nos permitirá realizar la navegación.
  • Permitir el acceso a los eventos de navegación.
public abstract class ViewModelBase : INotifyPropertyChanged
{
     private Frame appFrame;
     private bool isBusy;
 
     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 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;
     }
}

El acceso a los eventos de navegación lo lograremos implementando en la viewmodel los métodos abstractos OnNavigatedFrom y OnNavigatedTo. Esto no permite guardar y recuperar parámetros o estados.

Utilizando PageBase

En la carpeta Views añadiremos nuestras páginas. En nuestro ejemplo, tendremos dos páginas:

  • Pagina1
  • Pagina2

Cada página será un objeto de tipo PageBase, tanto en XAML:

<base:PageBase
    x:Class="Ejemplo_NavegacionMVVM02.Views.Pagina1"
    xmlns:base="using:Ejemplo_NavegacionMVVM02.Views.Base"
    mc:Ignorable="d"
    Background="LightCoral">
    <Grid>
 
    </Grid>
</base:PageBase>

Como en el code-behind:

/// <summary>
/// Pagina1.
/// </summary>
public sealed partial class Pagina1 : PageBase
{
     public Pagina1()
     {
         this.InitializeComponent();
     }
}

Añadimos en la primera página (Pagina1) un botón que permita navegar a la segunda página:

<Button Content="Navegar a página 2"
        HorizontalAlignment="Center"
        />

Para permitir navegar a la segunda página, necesitamos definir un comando en la viewmodel. Creamos una clase derivada de ViewModelBase:

public class Pagina1ViewModel : ViewModelBase
{
 
}

Implementamos los métodos de navegación definidos en ViewModelBase:

public class Pagina1ViewModel : ViewModelBase
{
     public override System.Threading.Tasks.Task OnNavigatedFrom(Windows.UI.Xaml.Navigation.NavigationEventArgs args)
     {
         return null;
     }
 
     public override System.Threading.Tasks.Task OnNavigatedTo(Windows.UI.Xaml.Navigation.NavigationEventArgs args)
     {
         return null;
     }
}

Y añadimos un comando que permita navegar de la página principal a la segunda página:

public class Pagina1ViewModel : ViewModelBase
{
     //Commands
     private ICommand _navigateCommand;
 
     public override System.Threading.Tasks.Task OnNavigatedFrom(Windows.UI.Xaml.Navigation.NavigationEventArgs args)
     {
         return null;
     }
 
     public override System.Threading.Tasks.Task OnNavigatedTo(Windows.UI.Xaml.Navigation.NavigationEventArgs args)
     {
         return null;
     }
 
     public ICommand NavigateCommand
     {
         get { return _navigateCommand = _navigateCommand ?? new DelegateCommand(NavigateCommandDelegate); }
     }
 
     public void NavigateCommandDelegate()
     {
         this.AppFrame.Navigate(typeof(Pagina2), "Esto es un parámetro");
     }
}

Recordamos que el control Frame hospeda controles Page
y tiene un historial de navegación que se puede utilizar para ir hacia
atrás y hacia adelante por las páginas que ya visitaste. Tras obtener el
Frame correspondiente, utilizamos el método Navigate para realizar la navegación a otra página. Tenemos dos sobrescrituras del método Navigate:

  • Navigate(TypeName). Provoca que el Frame cargue el contenido especificado por el tipo pasado como parámetro.
  • Navigate(TypeName, Object).
    En este caso, además de indicar el tipo del contenido a cargar (primer
    parámetro), podemos pasar un parámetro a la página que se navega(segundo
    parámetro).

En nuestro ejemplo hemos utilizado la segunda sobrescritura del método pasando un parámetro.

Ahora ,necesitamos conectar nuestra vista con nuestro viewmodel.
Podemos hacerlo de múltiples formas, desde el constructor de la vista,
instanciandola en App, usando Ioc. En nuestro caso, utilizaremos Ioc.
Usaremos Unity.

Una vez añadida la referencia correspondiente en cada proyecto (Windows y Windows Phone) creamos una nueva clase en la carpeta Base dentro de la carpeta ViewModels llamada ViewModelLocator:

public class ViewModelLocator
{
     readonly IUnityContainer _container;
 
     public ViewModelLocator()
     {
         _container = new UnityContainer();
 
         _container.RegisterType<Pagina1ViewModel>();
         _container.RegisterType<Pagina2ViewModel>();
     }
 
     public Pagina1ViewModel Pagina1ViewModel
     {
         get { return _container.Resolve<Pagina1ViewModel>(); }
     }
 
     public Pagina2ViewModel Pagina2ViewModel
     {
         get { return _container.Resolve<Pagina2ViewModel>(); }
     }
}

Sencillamente registramos nuestras viewmodels y creamos un par de
propiedades públicas por cada viewmodel para poder resolverlas y acceder
a ellas desde las vistas. A continuación, registramos nuestro locator en App.xaml que también tenemos en el proyecto Shared:

<locator:ViewModelLocator x:Key="Locator"/>

Asignamos la viewmodel como DataContext de nuestra viewmodel:

DataContext="{Binding Pagina1ViewModel, Source={StaticResource Locator}}"

Y todo preparado!. Nuestra segunda página sera similar a la primera (tipo PageBase):

<base:PageBase
    x:Class="Ejemplo_NavegacionMVVM02.Views.Pagina2"
    xmlns:base="using:Ejemplo_NavegacionMVVM02.Views.Base"
    mc:Ignorable="d"
    Background="LightSeaGreen"
    DataContext="{Binding Pagina2ViewModel, Source={StaticResource Locator}}">
    <Grid>
        <Button Content="Volver"
                HorizontalAlignment="Center"
                Command="{Binding NavigateBackCommand}"/>
    </Grid>
</base:PageBase>

Contará con su propia viewmodel:

public class Pagina2ViewModel : ViewModelBase
{
     //Commands
     private ICommand _navigateBackCommand;
 
     public override System.Threading.Tasks.Task OnNavigatedFrom(Windows.UI.Xaml.Navigation.NavigationEventArgs args)
     {
         return null;
     }
 
     public override System.Threading.Tasks.Task OnNavigatedTo(Windows.UI.Xaml.Navigation.NavigationEventArgs args)
     {
         if (args.Parameter != null)
             Debug.WriteLine(args.Parameter);
 
         return null;
     }
 
     public ICommand NavigateBackCommand
     {
         get { return _navigateBackCommand = _navigateBackCommand ?? new DelegateCommand(NavigateBackCommandDelegate); }
     }
 
     public void NavigateBackCommandDelegate()
     {
            this.AppFrame.GoBack();
     }
}

Utilizamos el método GoBack del Frame que navega al elemento más inmediato del historial de navegación, la página anterior.

Podéis descargar el ejemplo realizado a continuación:

Recordar qur cualquier duda o comentario lo podéis dejar en los comentarios.

Más información

[Cross Platform] Introducción a Xamarin.Forms (1/2)

Introducción

No hay duda, los smartphones han llegado, y ya forman parte de la
vida de todos nosotros. En muchos aspectos de nuestra vida accedemos a
información, realizamos algna tarea o sencillamente nos entretenemos con
uno de ellos.

Esto también nos afecta como desarrolladores. El desarrollo móvil se
ha convertido en una prioridad en una gran mayoria de ámbitos.

Actualmente contamos con varias plataformas dominantes:

  • iOS
  • Android
  • Windows Phone

Esto a nivel de desarrollo nos supone barreras. Contamos con
plataformas de desarrollo diferentes, lenguajes diferentes, etc.
suponiendo un nivel de aprendizaje y esfuerzo cada vez mayor de cara a
desarrolladores. Además, la experiencia nos ha demostrado que los
usuarios no aceptan aplicaciones no nativas. Los usuarios buscan aplicaciones rápidas, fluidas y con
consumos moderados, perfectamente adaptadas a la plataforma ofreciendo
una experiencia completa.

¿Qué podemos hacer para mejorar este panorama?

Xamarin.Forms

Con la reciente actualización a la versión 3 de Xamarin nos llega Xamarin.Forms. Es un toolkit para crear una abstracción sobre la interfaz de usuario de Android, iOS y Windows Phone permitiendo desarrollarla una única vez con código C# o Extensible Application Markup Language (XAML).

Xamarin.Forms nos permite crear aplicaciones para:

  • Android 4.0 o superior
  • iOS 6.1 o superior
  • Windows Phone 8.0

NOTA: Fijáos que hablamos de Windows Phone 8.0
con Silverlight. Incluso necesitamos usar el Toolkit de Windows Phone
para poder tener acceso a ciertos controles como por ejemplo el
DatePicker o a animaciones.

Nuestra primera aplicación Xamarin.Forms

Una vez instalada la versión 3 de Xamarin tendremos acceso a las nuevas soluciones Xamarin.Forms:

Contamos con las siguientes opciones:

  • Aplicación con Librería Portable: Crea una solución con un proyecto para cada plataforma junto a una librería portable donde añadir el código compartido.
  • Aplicación con proyecto Shared: Crea una solución
    con un proyecto para cada paltaforma junto a un cuarto proyecto Shared.
    Muy similar al concepto de aplicación universal en Windows Phone 8.1.
  • Librería portable: Crea una librería portable.

Creamos una aplicación con proyecto Shared.Contamos con la siguiente estructura de solución:

Por defecto se nos crea una aplicación de ejemplo muy básica con una única vista y un saludo en medio.

Analicemos el código fuente de la plantilla antes de continuar. La aplicación generada cuenta con una única página de tipo Xamarin.Forms.Page
que representa un Activity en Android, un View Controller en iOS y una
Page en Windows Phone. El tipo de página utilizada (posteriormente
veremos que contamos en Xamarin.Forms con múltiples tipos de páginas) es
Xamarin.Forms.ContentPage que cuenta con un Label como contenido.

En el proyecto compartido contamos con una clase llamada App. Esta
clase es la responsable de indicar cual sera la primera página a mostrar
en todas las plataformas.

public class App
{
    public static Page GetMainPage()
    {
        return new ContentPage
        {
            Content = new Label
            {
                Text = "Hello, Forms !",
                VerticalOptions = LayoutOptions.CenterAndExpand,
                HorizontalOptions = LayoutOptions.CenterAndExpand,
            },
        };
    }
}

En el caso por defecto, se crea con C# una instancia nueva de una
página de contenido y se le añade un Label centrado en pantalla.
Sencillo, ¿verdad?.

Una vez creada la página, en cada plataforma se debe:

  • Inicializar Xamarin.Forms
  • Proveer la página de contenido

Windows Phone

Debemos incializar Xamarin.Forms que lo haremos utilizando Forms.Init() además de establecer como contenido de la página nuestra Xamarin.Forms.ContentPage creada en App:

public partial class MainPage : PhoneApplicationPage
{
    public MainPage()
    {
        InitializeComponent();
 
        Forms.Init();
        Content = HelloXamarinFormsWorld.App.GetMainPage().ConvertPageToUIElement(this);
    }
}

Android

Con el MainLauncher creamos un Activity como en una aplicación normal Android, exceptuando que nuestro Activity hereda de Xamarin.Forms.Platform.Android.AndroidActivity. En el método OnCreate inicializamos Xamarin.Forms y establecemos nuestra página.

namespace HelloXamarinFormsWorld.Android
{
    [Activity(Label = "HelloXamarinFormsWorld", MainLauncher = true)]
    public class MainActivity : AndroidActivity
    {
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
 
            Xamarin.Forms.Forms.Init(this, bundle);
 
            SetPage(App.GetMainPage());
        }
    }
}

iOS

Por último,  en iOS, la clase AppDelegate inicializará Xamarin.Forms y establecerá el RootViewController a nuestra ContentPage de la clase App.

[Register("AppDelegate")]
public partial class AppDelegate : UIApplicationDelegate
{
    UIWindow window;
 
    public override bool FinishedLaunching(UIApplication app, NSDictionary options)
    {
        Forms.Init();
 
        window = new UIWindow(UIScreen.MainScreen.Bounds);
 
        window.RootViewController =  App.GetMainPage().CreateViewController();
 
        window.MakeKeyAndVisible();
 
        return true;
    }
}

Creando una App con C#

Hasta ahora hemos visto que Xamarin.Forms nos permite crear la
interfaz dde usuario de Windows Phone, Android e iOS de manera
compartida usando C# o XAML y hemos analizado el proyecto base creado
con las plantillas.

Continuamos profundizando cada vez más en Xamarin.Foms, vamos a crear
una primera aplicación sencilla utilizando el patrón MVVM y diseñando
la interfaz de usuario con C#.

Vamos a crear una aplicación que cuente con un botón, que al ser
pulsado ejecute  un comando en la viewmodel y actualice un texto con el
número de veces que el botón ha sido pulsado. Simple, pero suficiente
para ver muchos conceptos básicos.

Creamos un nuevo proyecto con la plantilla Blank App (Xamarin.Forms Shared). En el proyecto Shared creamos las carpetas:

  • Views
  • ViewModels

Dentro de la carpeta ViewModels, añadimos una carpeta Base donde vamos a añadir algunas clases base importantes para cubrir todas nuestras necesidades. Comenzamos añadiendo un ViewModelBase que se encargará de:

  • Notificar cambios
  • Notificar el estado
public abstract class ViewModelBase : INotifyPropertyChanged
{
     private Frame _appFrame;
     private bool _isBusy;
 
     public Frame AppFrame
     {
            get { return _appFrame; }
     }
 
     public bool IsBusy
     {
         get { return _isBusy; }
         set
         {
             _isBusy = value;
             RaisePropertyChanged();
         }
     }
 
     public event PropertyChangedEventHandler PropertyChanged;
 
     public void RaisePropertyChanged([CallerMemberName]string propertyName = "")
     {
         var Handler = PropertyChanged;
         if (Handler != null)
             Handler(this, new PropertyChangedEventArgs(propertyName));
     }
 
     internal void SetAppFrame(Frame viewFrame)
     {
         _appFrame = viewFrame;
     }
}

De esta clase heredarán todos nuestros viewmodels. Además, añadiremos otra clase importante, DelegateCommand.

Añadimos una nueva clase, llamada MainViewModel en nuestra carpeta ViewModels. Por supuesto, añadimos también otra clase llamada MainView que será la vista principal de nuestra aplicación, en la carpeta Views.

Comenzamos creando la vista de nuestra aplicación en C# (MainView).

public class MainView : ContentPage
{
 
}

Como podemos ver, nuestra clase hereda de ContentPage. En Xamarin.Forms contamos con distintos tipos de páginas:

  • ContentPage: Página de contenido que cuenta con una única vista donde añadir contenido.
  • MasterDetailPage: Página que gestiona dos paneles de información (maestro-detalle).
  • NavigationPage: Una página que gestiona una pila de otras páginas, la navegación y la experiencia de usuario entre ellas.
  • TabbedPage: Una página que permite el accesoa las subpáginas mediante tabs.
  • CarouselPage: Una página que permite acceder a las subpáginas haciendo un gesto de swipe (scroll lateral).

En nuestro ejemplo, elegimos la página más simple, ContentPage. A
continuación empezamos a añadir el contenido de nuestra página:

//Contenedor principal
var stack = new StackLayout
{
     Orientation = StackOrientation.Vertical,
     Padding = new Thickness(0, 10)
};

Comenzamos por un contenedor. El StackLayout es
un control de tipo contenedor, su cometido es organizar y posicionar
otros controles. Apila los controles por defecto verticalmente aunque
podemos controlar si apilamos de forma vertical o horizontal.

Contamos con múltiples controles de tipo contenedor aparte del StackLayout:

  • ScrollView: Contenedor que permite realizar scroll si el contenido lo requiere.
  • AbsoluteLayout: Posiciona los elementos mediante posiciones absolutas.
  • Grid: Contenedor potente que organiza los elementos mediante filsa y columnas.
  • RelativeLayout: Posiciona los elementos mediante constrainsts.

Continuamos con nuestro ejemplo, añadimos un texto informativo:

//Texto informativo
var info = new Label
{
     Font = Font.SystemFontOfSize(NamedSize.Medium),
     Text = "Hola Xamarin Forms!",
     LineBreakMode = LineBreakMode.WordWrap
};

Hemos añadido un control Label. Tras añadirlo, lo incluimos dentro de nuestro panel:

//Añadimos un botón. Al pulsarlo, actualizará el número de veces que lo pulsamos
var button = new Button
{
     Text = "Púlsame!"  
};
 
//Añadimos el botón a nuestro contenedor
stack.Children.Add(button);
 
var result = new Label
{
     Font = Font.SystemFontOfSize(NamedSize.Large)
};
 
//Añadimos el texto a nuestro contenedor
stack.Children.Add(result);

Hasta aquí toda nuestra inferfaz casi lista!. Nos faltan detalles
sumamente importantes como gestionar la lógica del botón al hacer clic.
En nuestra viewmodel:

public class MainViewModel : ViewModelBase
{
     private int _clicCounter;
 
     private DelegateCommand _helloCommand;
 
     public MainViewModel()
     {
         _clicCounter = 0;
     }
 
     public string Message
     {
         get { return string.Format("Botón pulsado {0} veces", _clicCounter); }
     }
 
     public ICommand HelloCommand
     {
         get { return _helloCommand = _helloCommand ?? new DelegateCommand(HelloCommandDelegate); }
     }
 
     private void HelloCommandDelegate()
     {
         _clicCounter++;
         RaisePropertyChanged("Message");
     }
}

Añadimos un comando que aumentará un contador que nos indicará las veces que se ha pulsado el botón y actualizará un mensaje.

Data Binding

Al igual que en el desarrollo de Windows Phone, el Data binding lo
usamos en Xamarin.Forms para mostrar e interactuar con la información.
Básicamente, establecemos un vínculo entre la interfaz de usuario y la
lógica de la aplicación.

En nuestro ejemplo, queremos vincular nuestra vista, MainView, con
nuestra viewmodel, MainViewModel. Para ello, utilizaremos la propiedad BindingContext:

// DataContext de la página, nuestro ViewModel
BindingContext = new MainViewModel();

Creamos también una propiedad de la viewmodel para que nuestra vista tenga acceso a propiedades y comandos de la viewmodel:

private MainViewModel ViewModel
{
     get { return BindingContext as MainViewModel; }
}

Nos faltaba establecer el comando HelloCommand de nuestra viewmodel al botón de nuestra interfaz:

var button = new Button
{
     Text = "Púlsame!",
     Command = ViewModel.HelloCommand
};

Por último, nos faltaba también añadir al segundo Label de la interfaz, el binding a la propiedad Message:

result.SetBinding(Label.TextProperty, "Message");

Utilizamos el método SetBinding. Este método espera dos parámetros:

El primer parámetro espera información sobre la propiedad en la que estableceremos el binding.

La segunda propiedad espera información sobre el binding. En la
mayoría de situaciones será una cadena con el nombre de la propiedad a
bindear del BindingContext.

Podéis descargar el ejemplo realizado a continuación:

Ahora con XAML!

Pues si, como ya hemos mencionado, podemos crear la interfaz de
usuario utilizando C# o XAML. El ejemplo exactamente igual que el
anterior pero trasladado a XAML. Para ello, en la carpeta Views, vamos a
añadir una Forms XAML Page. Clic derecho, añadir nuevo elemento:

<?xml version="1.0" encoding="utf-8" ?>
                       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                       x:Class="HolaXamarinFormsXAML.Views.MainView">
</ContentPage>

Añadimos nuestro contenedor junto a nuestros Labels y el botón:

<?xml version="1.0" encoding="utf-8" ?>
                       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                       x:Class="HolaXamarinFormsXAML.Views.MainView">
    <StackLayout Orientation="Vertical" Padding="0, 10">
        <Label Text="Hola Xamarin Forms!" />
        <Button Text="Púlsame!"  />
        <Label />
    </StackLayout>
</ContentPage>

Por último, establecemos los bindings:

<?xml version="1.0" encoding="utf-8" ?>
                       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                       x:Class="HolaXamarinFormsXAML.Views.MainView">
    <StackLayout Orientation="Vertical" Padding="0, 10">
        <Label Text="Hola Xamarin Forms!" />
        <Button Text="Púlsame!" Command="{Binding HelloCommand}" />
        <Label Text="{Binding Message}" />
    </StackLayout>
</ContentPage>

Al botón le bindeamos el comando HelloCommand y al segundo Label el
mensaje resultante. Como podemos ver, la forma de establecer bindings es
igual al utilizado en XAML de Windows Phone por ejemplo.

Podéis descargar el ejemplo realizado a continuación:

Llegando más lejos

Hasta ahora hemos visto bastantes detalles de Xamarin.Forms pero nos
queda aun camino por recorrer. Una aplicación con acceso a
características del sistema, múltiples páginas, ver como gestionar esto,
inyectar servicios entre otros puntos. Todo lo anterior lo veremos en
la continuación de este artículo.

Más información

[Universal Apps] Navegación entre páginas, paso de parámetros y gestión de la tecla volver (1/2)

Introducción

Casi cualquier aplicación que realices tendrá más de una página. Por lo que es vital saber como navegar entre ellas.

En
este artículo, vamos a aprender como se realiza la navegación entre
páginas en Windows Phone 8.1 además de aprender como gestionar la tecla
física atrás, gestionar el historial de navegación,etc.

¿Te apuntas?

Navegación entre páginas

Antes
de entrar de lleno a la navegación entre páginas en si. Vamos a
analizar una serie de conceptos básicos para entender todo el
funcionamiento del sistema de navegación.

Ahora, en Windows Phone 8.1, la App cuenta con una Window que contiene un único Frame que ocupa el 100% del área de la pantalla.

El Frame, se crea en el arranque de la aplicación y es el encargado de contener y gestionar cada una de las páginas (Page). Creamos una nueva aplicación desde cero, para ver donde se crea el Frame y como gestionamos la navegación.

Elegimos la plantilla de aplicación en blanco, la más básica, para centrarnos en la navegación entre páginas.

Si nos dirigimos a la clase App.xaml.cs, en el método OnLaunched, lanzado al arrancar la App, podemos ver la creación del Frame:

NOTA: El Frame también mantiene un historial de navegación de las páginas que han sido visitadas.

Añadimos un botón en la página principal de nuestra aplicación:

<Button Content="Navegar a página 2" HorizontalAlignment="Center" />

Antes de continuar, añadiremos una segunda página a la que navegaremos tras pulsar el botón. Seleccionamos el Proyecto, hacemos clic derecho y seleccionamos la opción Agregar. A continuación, seleccionamos la opción Nuevo elemento. Tras hacer clic en la opción nuevo elemento se nos abrirá el cuadro de diálogo Agregar nuevo elemento:

Añadimos una nueva página (en nuestro ejemplo llamada “Pagina2″) al
proyecto. Ahora ya podemos continuar con la navegación de la página
principal a la que acabamos de añadir.

Utilizamos el evento clic del botón:

<Button Content="Navegar a página 2" HorizontalAlignment="Center" Click="Button_Click"/>

Y en el code-behind:

private void Button_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
 
}

Y en el clic del botón:

private void Button_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
     Frame.Navigate(typeof(Pagina2));
}

Analicemos el código. Contamos con un modelo de navegación integrado que usa controles Frame y Page y funciona de manera similar a un navegador web. El control Frame hospeda controles Page
y tiene un historial de navegación que se puede utilizar para ir hacia
atrás y hacia adelante por las páginas que ya visitaste. Tras obtener el
Frame correspondiente, utilizamos el método Navigate para realizar la navegación a otra página. Tenemos dos sobrescrituras del método Navigate:

  • Navigate(TypeName). Provoca que el Frame cargue el contenido especificado por el tipo pasado como parámetro.
  • Navigate(TypeName, Object).
    En este caso, además de indicar el tipo del contenido a cargar (primer
    parámetro), podemos pasar un parámetro a la página que se navega(segundo
    parámetro).

En nuestro ejemplo hemos utilizado la primera sobrescritura del método sin pasar parámetro.

Volver atrás

Ahora, una vez en la segunda página, podemos programáticamente volver
a la página anterior. Añadimos un botón en la segunda página:

<Button Content="Volver" HorizontalAlignment="Center" Click="Button_Click"/>

Este botón nos permitirá volver a la página anterior. Añadimos el manejador del evento en el code-behind:

private void Button_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
 
}

En el clic del botón:

private void Button_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
     if (Frame.CanGoBack)
          Frame.GoBack();
}

Como hicimos previamente, vamos a analizar el sencillo código anterior. Utilizamos primero la propiedad CanGoBack que
nos devuelve un bool indicando si hay páginas en el historial de
navegación o no. Si existe historial de navegación utilizamos el método GoBack que navega al elemento más inmediato del historial de navegación.

NOTA: También contamos con la propiedad CanGoForward. Indica si en el historial de navegación existe una página delante de la actual.

Pasar parámetros

Ya hemos visto como navegar hacia delante y hacia atrás. Sin embargo,
en ocasiones, necesitamos pasar información entre las páginas. Ya hemos
visto que el método Navigate cuenta con una sobrescritura que nos
permite pasar parámetros.

Navigate(TypeName, Object).
En este caso, además de indicar el tipo del contenido a cargar (primer
parámetro), podemos pasar un parámetro a la página que se navega(segundo
parámetro).

En nuestro ejemplo modificamos la navegación de la página principal a la secundaria:

Frame.Navigate(typeof(Pagina2), "Podemos enviar un parámetro");

De manera similar a como ya hemos visto en Windows Phone, al navegar hacia o desde una página se ejecutan los métodos:

Para recuperar el String pasado como parámetro vamos a utilizar el método OnNavigatedTo que se ejecutará al entrar en la segunda página:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
     base.OnNavigatedTo(e);
      
     if (e.Parameter != null)
          Debug.WriteLine(e.Parameter);
}

En nuestro ejemplo, hemos recuperado el String y lo sacamos por la consola de depuración.

Sencillo, ¿cierto?.

Gestión de la tecla física atrás

En nuestra aplicación, estando en la segunda página podemos utilizar
también la tecla física como hacíamos en Windows Phone 8 para volver
atrás. Si la pulsamos… Ops!, ¿que ha ocurrido?

No hemos vuelto a la página anterior. En aplicaciones Windows XAML, al pulsar la tecla física atrás provoca una navegación a la App anterior no a la página anterior.

Podemos incluir código personalizado para anular este comportamiento y
causaruna navegación atrás dentro de la propia aplicación.

NOTA: En aplicaciones Silverlight 8.1 la navegación atrás es dentro de la propia aplicación.

En el archivo App.xaml.cs, en el constructor de nuestra aplicación añadimos:

HardwareButtons.BackPressed += HardwareButtons_BackPressed;

El evento será:

void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e)
{
     Frame frame = Window.Current.Content as Frame;
 
     if (frame == null)
          return;
 
     if (frame.CanGoBack)
     {
          frame.GoBack();
          e.Handled = true;
     }
}

Analizamos que hemos hecho. Cada vez que se pulse la tecla física
volver, entramos en nuestro código personalizado. Accedemos al Frame de
la aplicación, y si no es nulo, navegamos atrás y anulamos el
comportamiento por defecto.

Podéis descargar el ejemplo realizado a continuación:

Más información

[Windows Phone 8.1] Cambios en controles

Introducción

Con la llegada de nuevo SDK siempre esperamos
novedades significativas que nos permitan crear cada vez mejores
aplicaciones y otorgar experiencias de usuario más completas. Hasta
ahora, en determinadas ocasiones,  podíamos echar de menos algunos
controles que cubriesen necesidades básicas. Por ese motivo, en
ocasiones hemos analizado controles del Toolkit de Windows Phone, Coding4Fun, Cimbalino, MyToolkit y otras herramientas para suplir ciertas carencias.

Con
la llegada de este nuevo SDK muchos de estos aspectos se cubren
perfectamente además de conseguir controles comunes con la plataforma
Windows lo que nos permite compartir una mayor cantidad de código
también en XAML.

¿Te apuntas a descubrir todas las novedades disponibles en controles?

Que hemos dejado atrás

Hay
cambios importantes en controles muy básicos usados practicamente en
cualquier aplicación Windows Phone. Por este motivo, vamos a comenzar
hablando de los controles que “hemos dejado atrás”.

Hasta siempre Panorama, bienvenido Hub

Comenzamos
hablando del Panorama. Control usado como eje básico de muchas
aplicaciones. Permite mostrar una gran cantidad de información más alla
de los límites de la pantalla a la que accedemos realizando scroll
horizontal.

Pues… es nuestra primera pérdida. Pero, tranquilos!,
no, no perdemos ni se modifica dráticamente la experiencia de usuario
otorgada por el control Panorama ya que ha sido sustituido por el
control Hub.

<Hub Header="Header">
    <HubSection Header="Sub header 1">
        <DataTemplate>
            <Grid />
        </DataTemplate>
    </HubSection>
    <HubSection Header="Sub header 2">
        <DataTemplate>
            <Grid />
        </DataTemplate>
    </HubSection>
</Hub>

 WebBrowser pasa a ser WebView

Para aquellos que trabajasen con el control WebBrowser en Windows Phone, la llegada del WebView
no será un simple “cambio de nombre”. El control WebView llega cargado
de grandes cambios que permiten el trabajo con contenido HTML de forma
mucho más trasparente y sencilla.

<WebView />

Ahora en lugar del LongListSelector usamos el SemanticZoom

El
control LongListSelector era un control listado  avanzado que puede
mostrar dos listas, una  plana y otra agrupada. Ayuda a los usuarios a
navegar a través de largas listas, le permite saltar entre las
diferentes secciones de la lista mediante una rejilla que se superpone a
la lista cuando el usuario selecciona uno de los encabezados.

Ahora en su lugar usaremos el control SemanticZoom
ya existente en aplicaciones Windows Store previamente. El control
SemanticZoom a pesar de no ser un control listado es mucho más potente.
Cuenta con dos estados ZoomedInView y ZoomedOutView. De esta forma
podemos permitir cambiar entre las dos vistas de manera sencilla
incluyendo un control lista en la vista ZoomedIn y un GridView en la
vista ZoomedOut.

RickTextBox es ahora RichTextBlock

Este control nos permite texto con formato: imágenes en líneas, enlaces y otro tipo de contenido enriquecido.

<RichTextBlock>
    <Paragraph>
        <Bold>Interesante<Bold> control
    </Paragraph>
</RichTextBlock>

Adios MultiScaleImage

Este
control ha quedado atrás sin sustituto directo. Permitía utilizar
imágenes con múltiples resoluciones y realizar diferentes gestos. Sin
embargo, podemos utilizar en su lugar el control Image por defecto.

<MultiScaleImage Source="source/source.xml" />

NOTA: Si actualizamos una aplicación existente a Silverlight 8.1 el control seguirá estando disponible.

CommandBar

El control CommandBar esta compartido entre Windows y Windows Phone. Nos permite crear application bars con facilidad.

<Page.BottomAppBar>
        <CommandBar x:Name="commandBar">
            <CommandBar.PrimaryCommands>
                <AppBarButton Label="edit" Icon="Edit" />
                <AppBarButton Label="favorite" Icon="Favorite" />
                <AppBarSeparator />
                <AppBarToggleButton Label="play" Icon="Play" />
            </CommandBar.PrimaryCommands>
            <CommandBar.SecondaryCommands>
                <AppBarButton Label="help" Icon="Question" />
            </CommandBar.SecondaryCommands>
        </CommandBar>
</Page.BottomAppBar>



NOTA: En Windows Phone sustituye al control
ApplicationBar. En Windows existe también el control AppBar, la
diferencia recae en el tipo de contenido que puede albergar, el
CommandBar solo puede contener controles ICommandBarElement.

Que hay de nuevo

Una
gran cantidad de controles estan disponibles en Windows 8.1 y Windows
Phone 8.1 pero no es asi con todos. A continuación, vamos a ver una
introducción a controles nuevos disponibles en Windows Phone 8.1:

PickerFlyout

Flyout con una propiedad llamada ConfirmationButtonsVisible que nos permite mostrar los botones aceptar/cancelar en la parte inferior del flyout.

var pickerFlyout = new PickerFlyout();
var textBlock = new TextBlock { Text = "flyout textblock", FontSize = 24 };
pickerFlyout.Content = textBlock ;
pickerFlyout.ConfirmationButtonsVisible = true;
await pickerFlyout.ShowAtAsync(targetFrameWorkElement);

DatePickerFlyout

Podemos mostrar un flyout que permite seleccionar fechas:

var datePickerFlyout = new DatePickerFlyout();
await datePickerFlyout.ShowAtAsync(targetFrameWorkElement);

TimePickerFlyout

Control muy similar al DatePickerFlyout permitiendo seleccionar horas en lugar de fechas.

var timePickerFlyout = new TimePickerFlyout();
await timePickerFlyout.ShowAtAsync(targetFrameWorkElement);

ListPickerFlyout

Flyout que muestra un listado indicado por la propiedad ItemsSource.

var listPickerFlyout = new ListPickerFlyout();
listPickerFlyout.ItemsSource = source;
await listPickerFlyout.ShowAtAsync(targetFrameWorkElement);

AutoSuggestBox

Control
totalmente nuevo exclusivo de Windows Phone 8.1 (en Windows podemos
conseguir lo mismo de otras formas).  Muestra una caja de texto de modo
que segun el usuario va escribiendo, va recibiendo sugerencias. Las
sugerencias las podemos indicar gracias a la propiedad ItemsSource:

<AutoSuggestBox TextChanged="AutoSuggestBox_TextChanged"
    ItemsSource="{Binding Suggestions}">
    <AutoSuggestBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding}"/>
        </DataTemplate>
    </AutoSuggestBox.ItemTemplate>
</AutoSuggestBox>

private void AutoSuggestBox_TextChanged(AutoSuggestBox sender,
        AutoSuggestBoxTextChangedEventArgs args)
{
    if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput)
    {
        Suggestions.Clear();
        Suggestions.Add(sender.Text + "1");
        Suggestions.Add(sender.Text + "2");
        Suggestions.Add(sender.Text + "3");
        Suggestions.Add(sender.Text + "4");
        Suggestions.Add(sender.Text + "5");
    }
}

A su vez, tenemos eventos para determinar cada vez que el usuario escribe para poder cambiar las sugerencias dinámicamente.

ContentDialog

Control que nos permite crear mensajes popups personalizados.

private async void ShowContentDialog()
{
    ContentDialog dialog = new ContentDialog()
    {
        Title = "Download updates?",
        Content = "This update will clean the slate for Iron Man",
        PrimaryButtonText = "Yes, clean it",
        SecondaryButtonText = "No, Dont!"
    };
    dialog.SecondaryButtonClick += dialog_SecondaryButtonClick;

    ContentDialogResult result = await dialog.ShowAsync();
    if (result == ContentDialogResult.Primary) { /* do some more Primary logic */ }
    else if (result == ContentDialogResult.Secondary) { /* else do Secondary logic */ }
}

Podemos mostrar el popup en modo a pantalla completa o de forma parcial.

Controles compartidos con Windows

Tenemos
un gran listado de controles que son exactamente iguales (en
funcionalidad, comportamiento, nombres, namespaces, etc.) tanto en
Windows 8.1 como en Windows Phone 8.1. Esto nos facilita enormemente la
tarea de compartir código entre ambas plataformas.

De los controles vistos previamente, algunos de ellos, cumplen esta característica:

  • Hub
  • SemanticZoom
  • WebView

Además
de los ya nombrados tenemos otros nuevos o que ya existían para crear
aplicaciones Windows Store y llegan por primera vez a la plataforma
Windows Phone.

DatePicker

No
podía continuar por otro control. Cumple unas necesidades básicas que
hasta ahora teníamos que cubrir con el Toolkit de Windows Phone u otras
herramientas. Por fin llega a Windows Phone un control para introducir
fechas de manera fácil e intuitiva de la misma forma que lo hacíamos
hasta ahora usando el Toolkit por ejemplo, pero de forma directa con el
SDK.

<DatePicker/>

Además llega localizado entre otra serie de características que nos facilitan mucho su uso.

TimePicker

Al igual que el anterior, este control también era muy esperado. Control usado para insertar horas en nuestras aplicaciones.

<TimePicker/>

Frame

En las aplicaciones de la plataforma Windows, usamos un objeto de tipo Frame
que contendrá cada una de las páginas que componen la aplicación
permitiendo la navegación entre ellas. Hasta ahora, el control Frame de
Windows Phone y Windows eran diferentes. Ya son iguales. Esto permite
utilizar el mismo sistema de navegación en ambas plataformas. Contiene
comandos para regresar hacia atrás o navegar a otras páginas.

ProgressRing

Control
que ya teníamos en aplicaciones Windows Store pero no en Windows Phone
donde contábamos con el control ProgressIndicator. Este control muestra
un progreso con una serie de puntos que giran formando un círculo.

<ProgressRing IsActive="True"/>

ListView

Control ya habitual en aplicaciones Windows Store que ahora es común a ambas plataformas. El control ListView es una lista vertical que hereda del control ListBox siendo más flexible permitiendo el uso del SemanticZoom asi como el uso de columnas, diferentes vistas, etc.

<ListView ItemsSource="{Binding Items}" />

También el control GridView

Uno de los controles principales desde la llegada de Windows 8 ahora es común a ambas plataformas. El control GridView un listado con scroll horizontal (por defecto) que funciona y permite unas opciones similares al ListView.

<GridView ItemsSource="{Binding Items}" />

ToggleSwitch

En
Windows Phone teníamos el control CheckBox al que podíamos lograr
asignarle un aspecto visual similar al control ToggleSwitch disponible
en aplicaciones Windows Store. Además, podíamos utilizar librerías de
terceros para conseguir el resultado. Ya no será necesario realizar
ninguna de las dos tareas ya que tenemos incluido el control en el SDK
de manera compartida entre plataformas.

<ToggleSwitch x:Name="toggleSwitch1" Header="ToggleSwitch"
              OnContent="On" OffContent="Off"
              Toggled="ToggleSwitch_Toggled"/>

NOTA: Utiliza el color Accent del teléfono para resaltar el Switch al estar activado.


Flyout

Con
este control podemos crear nuestros flyouts totalmente personalizados.
Puede contener cualquier tipo de control que necesitemos.

<Flyout>
    <StackPanel>
        <TextBlock>Flyout</TextBlock>
        <Button>Clic</Button>
    </StackPanel>
</Flyout>

En Windows Phone se posiciona en la parte superior de la pantalla
mientras que en Windows se posicionará en la parte superior del control
target.

MenuFlyout

Es el nuevo context menu. Muy similar al control anterior con la diferencia básica recayendo en el contenido. El control MenuFlyout solo puede contener MenyFlyoutItem, ToggleMenuFlyout y MenuFlyoutSeparator.

<Page.BottomAppBar>
  <CommandBar>
    <AppBarButton Icon="Camera" Label="brag">
      <AppBarButton.Flyout>
        <MenuFlyout>
          <MenuFlyoutItem Text="Photo" />
          <MenuFlyoutItem Text="Video" />
        </MenuFlyout>
      </AppBarButton.Flyout>
    </AppBarButton>
    <AppBarButton Icon="Pin" Label="Like"/>
  </CommandBar>
</Page.BottomAppBar>

WrapGrid

Panel
que posiciona los elementos secuencialmente de izquierda a derecha o de
arriba a abajo. Cuando un elemento excede el tamaño del panel, se
posiciona en la siguiente fila o columna.

<ListView.ItemsPanel>
     <ItemsPanelTemplate>
          <WrapGrid Orientation="Horizontal" MaximumRowsOrColumns="2"/>
     </ItemsPanelTemplate>
</ListView.ItemsPanel>

NOTA: Se utiliza para cambiar la forma de posicionamiento en un control ItemsControl.

VariableSizedWrapGrid

Panel que permite organizar a sus elementos en filas y columnas. Cada elemento puede ocupar más de una fila y/o columna.

<VariableSizedWrapGrid MaximumRowsOrColumns="3" ItemHeight="44" ItemWidth="44">
    <Rectangle Fill="Red"/>
    <Rectangle Fill="Blue" Height="80"
               VariableSizedWrapGrid.RowSpan="2"/>
    <Rectangle Fill="Green" Width="80"
               VariableSizedWrapGrid.ColumnSpan="2"/>
    <Rectangle Fill="Yellow" Height="80" Width="80"
               VariableSizedWrapGrid.RowSpan="2"
               VariableSizedWrapGrid.ColumnSpan="2"/>
</VariableSizedWrapGrid>

NOTA: VariableSizedWrapGrid no usa virtualización, puede impactar en el rendimiento.


Más información

[Windows Phone 8.1] Introducción al Geofencing

Introducción

En el paso de Windows Phone 7 a Windows Phone 8, los desarrolladores
conseguimos una serie de características nuevas muy interesantes que se
traducieron en nuevas aplicaciones que ofrecían nuevas experiencias para
los usuarios antes imposibles. Ahora con la llegada de Windows Phone
8.1 nos llegan las APIs de Geofencing pudiendo crear de nuevo, nuevas experiencias.

¿Qué es el Geofencing?

El Geofencing es una tecnología que permite definir límites virtuales
en el mundo real. De esta forma, se puede establecer un radio de
interés dentro del cual lanzar algun tipo de acción concreta.

El potencial es altamente elevado, desde recibir recordatorios del
interés del usuario segun zonas geográficas  a recibir ofertas o
descuentos segun tiendas en la zona.

Manos a la obra

Creamos una nueva aplicación Windows Phone 8.1 con el objetivo de analizar todas las capacidades del geofencing.

Para poder utilizar geofencing lo primero que debemos hacer es dirigirnos al archivo AppxManifiest y activar la capacidad de Localización.

Comenzamos a trabajar con la API de geofencing. Debemos crear al
menos una zona geográfica, un punto marcado por coordenadas, en el cual
establecer un radio para detectar cuando se entra o sale del mismo y
actuar en consecuencia.

Comenzamos creando un objeto de tipo GeofenceMonitor.
Sera el encargado de gestionar la información relacionada con las áreas
establecidas asi como notificar cuando el usuario entra o sale de las
mismas:

GeofenceMonitor _monitor = GeofenceMonitor.Current;

Creamos un método para crear geofence:

private void NewGeofence(string id, double latitude, double longitude, double radius)
{
     // Establecemos la posición del Geofence.
     var position = new BasicGeoposition
     {
          Latitude = latitude,
          Longitude = longitude
     };
 
     //
El Geofence es un círculo centrado en el punto dado por la latitud y la
longitud con el radio asignado en la propiedad radius.
     var geocircle = new Geocircle(position, radius);
 
     // Queremos gestionar los eventos al entrar en la zona.
     const MonitoredGeofenceStates state = MonitoredGeofenceStates.Entered;
 
     // Tiempo que el usuario debe estar en el área para recibir la notificación.
     var dwellTime = TimeSpan.FromSeconds(5);
 
     // Añadimos el Geofence al GeofenceMonitor.
     var geofence = new Geofence(id, geocircle, state, false, dwellTime);
 
     if (!GeofenceMonitor.Current.Geofences.Contains(geofence))
          GeofenceMonitor.Current.Geofences.Add(geofence);
}

Que llamaremos desde el constructor de nuestra viewmodel:

// Creamos un Geofence.
NewGeofence("Windows Phone Developer", 37.3823, -5.9702, 150);

¿Que hacemos exactamente en este método?

Vamos a desglosarlo paso a paso. Necesitamos crear un área circular
que se establece en el punto marcado por latitud y longitud, con un
radio establecido por la propiedad radius.  Este círculo lo establecemos
utilizando un objeto de tipo Geocircle definido por un objeto de tipo BasicGeoposition que cuenta con las coordenadas además del radio.

Tras definir el círculo, indicamos cuando se lanzaran los eventos
gracias a la enumeración del tipo MonitoredGeofenceStates. Podemos
establecerlo a:

  • None
  • Entered
  • Exited
  • Removed

Nos permite indicar si se lanza el evento GeofenceStateChanged al entrar, salir o eliminar la zona.

Por último, creamos un objeto de tipo Geofence pasandole
los parámetros anteriores, la enumeración MonitoredGeofenceStates, el
objeto Geocircle, un TimeSpan que indica el tiempo que debe estar el
usuario en la zona para saltar la notificación y además de todo lo
anterior, es necesario un identificador único de la zona. No podemos
establecer zonas duplicadas.

_monitor.GeofenceStateChanged += MonitorOnGeofenceStateChanged;

En el constructor de nuestra viewmodel nos suscribimos tambien al evento GeofenceStateChanged. Este evento se lanzará cada vez que algun objeto de la colección de zonas del GeofenceMonitor cambie:

private void MonitorOnGeofenceStateChanged(GeofenceMonitor sender, object args)
{
     var fences = sender.ReadReports();
 
     foreach (var report in fences)
     {
          if (report.Geofence.Id != "Windows Phone Developer")
               continue;
 
          switch (report.NewState)
          {
               case GeofenceState.Entered:
                     _dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
                     {
                          await _dialogService.Show("Hola!");
                     });
                     break;
          }
     }
}

Cuando recibimos una notificación, usamos el método ReadReports. Este método devuelve la colección de Geofences que han cambiado su estado.

En cada una de las Geofences con nuevo estado, podemos controlar cual
es, y que acción realizar en cada estado, si se esta entrando o
saliendo de la zona por ejemplo. En nuestro ejemplo, utilizamos el
servicio DialogService (inyectado en la viewmodel) para mostrar un
simple mensaje.

NOTA: Podéis utilizar el emulador de Windows Phone con la herramienta extra de localización para simular posiciones.

Podéis descargar el ejemplo realizado a continuación:

Conclusiones

Las opciones que nos brinda el Geofencing son muy elevadas pudiendo
contar con características muy interesantes además con una API muy
sencilla de utilizar.

En este artículo hemos hecho una introducción a las APIs de
Geofencing. En próximos artículos veremos como utilizar la API junto a
acciones en background lo que potencian aun mas las posibilidades.

Recordar que cualquier tipo de duda la podéis dejar en los comentarios.

Más información

[Windows Phone 8.1] La nueva CommandBar

Introducción

En la plataforma Windows el peso principal de
las aplicaciones recae en el contenido de las mismas. Para lograr este
objetivo, separamos los comandos y las acciones del contenido principal.
En Windows Phone hasta ahora, la forma habitual para conseguir esto era
mostrando un menu de opciones era usando el ApplicationBar,
barra situada en la parte inferior de la pantalla. En Windows 8
contábamos con dos tipos de app bar, uno en la parte inferior usado para
agrupar las acciones de la aplicación y otro en la parte superior
utilizado habitualmente para otorgart al usuario de una experiencia de
navegación avanzada.

En Windows 8.1 y en Windows Phone 8.1 se introduce un nuevo concepto llamado CommandBar, una nueva forma de crear app bars compartida y sencilla.

En este artículos vamos a ver:

  • Implementar CommandBar en aplicaciones Windows y Windows Phone
  • Gestión de iconos en los AppBarButton de la CommandBar
  • MenuFlyouts desde la CommandBar

El control CommandBar

El control CommandBar esta compartido entre Windows y Windows Phone. Nos permite crear application bars con facilidad.

<Page.BottomAppBar>
    <CommandBar>
    </CommandBar>
</Page.BottomAppBar>

NOTA: En Windows Phone sustituye al control
ApplicationBar. En Windows existe también el control AppBar, la
diferencia recae en el tipo de contenido que puede albergar, el
CommandBar solo puede contener controles ICommandBarElement.

Sólo puede contener controles que deriven de ICommandBarElement:

AppBarButton

Cuenta con tres propiedades básicas:

  • Label: Usado para el texto que aparece debajo del botón.
  • Icon: Permite definir el icono utilizado en el botón. El icono debe ser representativo de la acción que ejecuta.
  • IsCompact: Fuerza al AppBarButton a utilizar el
    modo compacto. En este caso, se oculta el texto del label para reducir
    el tamaño y márgenes del mismo.
<AppBarButton Icon="Add" Label="Add" />

En el ejemplo anterior la propiedad Icon la rellenamos con una simple
cadena que especifica el identificador del icono. La propiedad Icon es
de tipo IconElement. Tenemos cuatro opciones, cuatro clases que heredan de IconElement:

  • BitmapIcon: Se utiliza una imagen para definir el icono. Lo haremos utilizando la propiedad UriSource:
<AppBarButton Label="Add">
    <AppBarButton.Icon>
        <BitmapIcon UriSource="ms-appx:///Assets/Add.png" />
    </AppBarButton.Icon>
</AppBarButton>

NOTA: Podemos utilizar una Windows Store URI como ms-appx o ms-appdata.

  • FontIcon: Se utiliza una fuente específica para definir el icono.

La clase FontIcon cuenta con dos propiedades principales. Por un lado contamos con la propiedad Glyph usada para indicar el código del carácter utilizado y por otro lado FontFamily usada para indicar la fuente.

<AppBarButton Label="Mail">
    <AppBarButton.Icon>
        <FontIcon FontFamily="Segoe UI Symbol" Glyph="" />
    </AppBarButton.Icon>
</AppBarButton>
  • PathIcon: Se utiliza un Path para definir el icono. Utilizamos la propiedad Data para indicar la figura a dibujar:
<AppBarButton Label="Path">
    <AppBarButton.Icon>
        <PathIcon Data="F1 M 20,20L 24,10L 24,24L 5,24" />
    </AppBarButton.Icon>
</AppBarButton>
  • SymbolIcon: Se utiliza la fuente Segoe UI Symbol para
    representar al icono. Esta opción es la que se utiliza por defecto
    cuando pasamos una cadena en la propiedad Icon.
<AppBarButton Icon="AllApps" Label="apps" />

SymbolIcon define una propiedad Symbol para definir el icono. Symbol es una enumeración que contiene cada uno de los iconos que podemos usar:

public enum Symbol
{
    Previous = 57600,
    Next = 57601,
    ...
}

Es muy simple de usar:

<AppBarButton Label="Calendar">
    <AppBarButton.Icon>
        <SymbolIcon Symbol="Calendar" />
    </AppBarButton.Icon>
</AppBarButton>

AppBarToggleButton

Control sumamente similar al AppBarButton, con sus mismas propiedades
principales, Label, Icon e IsCompact. La diferencia principal radica en
que este control cuenta con dos estados: checked y un checked.

La definición es muy similar a lo anterior:

<AppBarToggleButton                     
Label="Shuffle"                  
Checked="ShuffleAppBarButton_Checked"              
Unchecked="ShuffleAppBarButton_Unchecked">
    <AppBarToggleButton.Icon>
        <SymbolIcon Symbol="Shuffle" />
    </AppBarToggleButton.Icon>
</AppBarToggleButton>

Podemos controlar el estado:

private void ShuffleAppBarButton_Checked(object sender, RoutedEventArgs e)
{
  
}
  
private void ShuffleAppBarButton_Unchecked(object sender, RoutedEventArgs e)
{
 
}

AppBarSeparator

El control AppBarSeparator es muy sencillo, dibuja una línea vertical con el objetivo de separar controles del CommandBar.

<AppBarSeparator Foreground="White" />

Continuamos profundizando en el control CommandBar. Cuenta con dos propiedades principales:

  • PrimaryCommands: Colección de comandos principales
    de la página. En aplicaciones Windows Store se muestran automáticamente
    en la parte derecha del CommandBar. En aplicaciones Windows Phone se
    muestran como botones del CommandBar.
  • SecondaryCommands: Colección de comandos
    secundarios de la página. En aplicaciones Windows Store se muestran
    automáticamente en la derecha del CommandBar. En aplicaciones Windows
    Phone se muestran como elementos de menu del CommandBar.

NOTA: Si no especificamos ninguna colección en concreto, los controles se añadirán a la colección PrimaryCommands.

<Page.BottomAppBar>
        <CommandBar Background="DarkOrange">
            <AppBarButton Icon="AllApps" Label="apps" />
            <AppBarButton Icon="Emoji" Label="emotion" />
            <AppBarSeparator Foreground="White"/>
            <AppBarButton Icon="Pin" Label="pin" />
            <AppBarButton Icon="Refresh" Label="refresh"/>
            <CommandBar.SecondaryCommands>
                <AppBarButton Icon="Help" Label="help" />
            </CommandBar.SecondaryCommands>
        </CommandBar>
</Page.BottomAppBar>

MenuFlyouts. Añadir menus

En ocasiones tenemos la necesidad de contar con varios botones
relacionamos profundamente en su cometido. Por ejemplo, tenemos un
listado de elementos y en la CommandBar queremos permitir filtrar por:

  • Puntuación
  • Descargas

¿Añadimos dos botones a la CommandBar?. Es una opción, aunque sin
duda añadir un menu que aparezca al pulsar un simple botón filtrar es
una opción mejor. Veamos como sería.

Añadimos un MenuFlyout a la propiedad Flyout de un botón:

<AppBarButton Icon="AllApps" Label="apps">
     <AppBarButton.Flyout>
          <MenuFlyout>
                         
          </MenuFlyout>
     </AppBarButton.Flyout>
</AppBarButton>

Por último, añadimos elementos MenuFlyoutItem al Menu:

<AppBarButton Icon="AllApps" Label="apps">
     <AppBarButton.Flyout>
          <MenuFlyout>
               <MenuFlyoutItem Text="App01"/>
               <MenuFlyoutItem Text="App02"/>
          </MenuFlyout>
      </AppBarButton.Flyout>
</AppBarButton>

El comportamiento de los MenuFlyOutItem es similar al de los botones teniendo capacidad de poder hacer data binding:

<AppBarButton Icon="AllApps" Label="apps">
     <AppBarButton.Flyout>
          <MenuFlyout>
               <MenuFlyoutItem Text="App01"  Command="{Binding MenuFlyoutCommand}"/>
               <MenuFlyoutItem Text="App02"/>
          </MenuFlyout>
      </AppBarButton.Flyout>
</AppBarButton>

Podéis descargar la aplicación universal de ejemplo a continuación:

Diseño

Al utilizar el mismo código en aplicaciones universales tenemos
ciertas peculiaridades en el diseño y forma de interactuar con la
CommandBar dependiendo de si estamos en una aplicación de teléfono o de
tableta.

Al añadir AppBarButton al CommandBar por defecto se colocan en la
colección de botones PrimaryCommands. En aplicaciones Windows Store los
botones de la colección PrimaryCommands se situan a la derecha mientras
que los botones de la SecondaryCommands se situan en la izquierda:

Mientras que en Windows Phone, el mismo código coloca los botones de la colección SecondaryCommands como elementos de menu:

NOTA: El icono del botón es ocultado de manera automática.

Añ añadir MenuFlyouts a un botón de la CommandBar, el aspecto en Windows Store es el siguiente:

En Windows Phone, tenemos esta novedad que aparece con una animación con el siguiente aspecto:

Más información

Material de “De WP8 a WP8.1″ en el Gusenet

El evento

Este fin de semana se ha celebrado el evento “Back To My Roots”
de Gusenet, el Grupo de Usuarios .NET del sureste. Tras una superación
año tras año, este año ha habido una participación expectacular con una
excelente asistencia, un número elevado de charlas con ponentes de un
enorme nivel y una variedad temática sorprendente.

Además de poder disfrutar de las charlas, hablar y desvirtualizar a
muchos  de los asistentes, tuve la oportunidad de poder participar con
una charla en el evento.

La charla

Con la llegada de Windows Phone 8.1 tenemos nuevas formas posibles de
desarrollar nuestras aplicaciones. Por un lado se habla de Silverlight
8.1, por otro de Windows XAML, WinJS, etc. La idea de la charla era:

  • ¿Que diferencia hay entre Silverlight 8.1 y Windows XAML?
  • ¿Si ya tengo una App Windows Phone 8.0, que uso?
  • ¿Y si es Windows Store?

En Windows Phone 8.1 podemos desarrollar con:

  • Silverlight Windows Phone 8.0: Todas las
    aplicaciones Windows Phone 8.0 funcionan en Windows Phone 8.1 aunque
    evidentemente sin tener acceso a las nuevas APIs.
  • Silverlight 8.1: Nueva versión destinada a migrar aplicaciones con rapidez y sencillez.
  • Windows XAML: Gran novedad, llega a Windows Phone
    una nueva versión de XAML, el ya usado en aplicaciones WinRT. La
    convergencia entre las paltaformas se potencia gracias a esta nueva
    opción dando lugar a los proyectos universales.
  • WinJS: Permite desarrollar aplicaciones nativas con
    HTML5, CSS y JS. Ahora además de aplicaciones Windows Store permite
    crear aplicaciones Windows Phone, incluso aplicaciones universales.

Las conclusiones básicas de la charla fueron:

  • Si tienes una aplicación Windows Phone 8.0 y no necesitas ninguna de
    las nuevas APIs disponibles en Windows Phone 8.1 no tienes que hacer
    nada. Las aplicaciones Windows Phone 8.0 funcionan en los dispositivos
    Windows Phone 8.1.
  • Si tienes una aplicación Windows Phone 8.0 y quieres utilizar las
    nuevas APIs de Windows Phone 8.1, Silverlight 8.1 es una buena opción.
    Silverlight 8.1 nos permite migrar aplicaciones con suma facilidad. Si
    tu aplicación utiliza:

    • CameraCaptureTask
    • Camera Lenses
    • Lockscreen background image provider
    • Alarmas
    • Recordatorios

Silverlight 8.1 es tu opción ya que estas opciones son exclusivas de Silverlight.

  • Sin embargo, hay opciones disponibles en Windows Phone 8.0 que no
    estan disponibles en Silverlight 8.1 como por ejemplo Background Audio.
    En este caso Windows XAML es la opción adecuada.
  • Si partimos de una aplicación Windows Store, Windows XAML es más directo.
  • Si partimos de una aplicación Windows Store desarrollada con WinJS, utilizar WinJS para Windows Phone es lo más idóneo.
  • Si partimos de cero, podemos elegir entre Windows XAML, WinJS o
    Silverlight 8.1. Todo depende de los conocimientos que tengas en los
    lenguajes y que quieras realizar. Si quieres cubrir teléfonos y tabletas
    (aplicaciones Windows Phone y Windows Store), realizar una aplicación
    universal es lo más idóneo.

El material

Os dejo a continuación la presentación utilizada:

 

Además de los ejemplos. Partimos de una aplicación Windows Phone 8 que podéis descargar a continuación:

Realizamos
la migración a Windows Phone 8.1 ( la aplicación Windows Phone 8.0
contaba con alarmas, por lo que era la opción más adecuada):

Posteriormente a una aplicación Universal (sin añadir la opción de recordatorios de la aplicación original):

No quisiera terminar sin agradecer a todos que este tipo de eventos sean posibles, asistentes, ponentes y por supuesto a Eladio Rincón, Oscar Montesinos y Pedro Hurtado
organizadores del evento. Gusenet ha sido un gran evento donde aprender
y compartir muchos conocimientos, con un ambiente excepcional que nos
ha dejado un divertido fin de semana.

Hasta el año que viene Gusenet!

Más información

[Evento] Gusenet, back to my roots

El evento

Tras superarse cada año y “liarla” el año pasado con “Yo Node, tú
XAML”, nos llega este año “Back to my roots” por parte de los chicos de gusenet.
Un megaevento donde se hablará de muchísimas tecnologías distintas;
AngularJS, Test unitarios, JavaScript , Microsoft Azure, Firefox OS,
Android, Windows Phone, etc., habrá muchísimo networking, posibilidades
de aprender, compartir y… hasta cerveza gratis!. Todo ello en un lugar
inmejorable cerca de la costa, invitándonos a pasar un gran fin de
semana tecnológico.

Fechas

Tendrá lugar los días 25, 26 y 27 de Abril en Torrevieja con la siguiente agenda:

Viernes, 25 de Abril

  • 20:00 Quedada en la puerta del Palacio o el Bar El Palco para cenar.

Sábado, 26 de Abril

  • 9:00 – 11:15 Presentación y ponencias.
  • 11:15-11:35 Café. (cortesía de algún patrocinador)
  • 11:35-14:30 Ponencias
  • 14:30-15:00 Cervezas
  • 15:15- 16:30 Comida en el hotel buffet de 10 €
  • 16:30-21:00 Ponencias en el Palacio de la Música
  • 16:30-XX:XX Ponencias en El Palco (Bar del evento)

Domingo, 27 de Abril

  • 12:00 Actividad lúdica o tapeo por el paseo marítimo de Torrevieja.

Lugar

El evento se celebrará en Levante, más concretamente en Torrevieja, en el conservatorio de música.

La agenda

El día 26 tendremos una enorme cantidad de sesiones técnicas de 30 minutos
de duración. Yo tendre el placer de poder participar con una charla
sobre Windows Phone 8.1 en la que veremos como portar una aplicación
existente de Windows Phone 8 a la nueva versión, que posibilidades
tenemos, ventajas e inconvenientes de cada una, etc. Además de esta
sobre Windows Phone tenemos una cantidad abrumadora de ponentes de lujo.
Tenéis una agenda de las charlas a continuación:

Ponente Charla
Marc Estrada Pague una, llévese dos (apps para múltiples dispositivos).
Marc Rubiño AngularJS – Poli bueno, poli malo.
Juan María Hernández No pierdas tiempo escribiendo tests.
Alfredo Fernández Todo un misterio (es secreto: probablemente algo cañero de JS).
Juan Quijano Coded UI, iniciación a pruebas funcionales del interfaz gráfico.
Quique Martínez Video OnDemand y Live Streaming. Entrega de vídeo multiplataforma.
Luis Ruíz Pavón CQRS – Hasta el infinito y más allá
Alberto Díaz & Adrián Díaz Porque no veo otra cosa nada más que SharePoint
Pedro J. Molina Backends y arquitecturas para servicios con Radarc

Google Glass

Alex Casquete Programación funcional reactiva
Eduard Tomás Videojuegos web en tiempo real con Katana, SignalR y NancyFx
Roberto Luis Bisbé Firefox OS: Javascript vuela en primera clase
Enrique Catalá Nuevo motor relacional In-memory OLTP en SQL Server 2014
Bruno Capuano Coding 4 Fun, Kinect V2, Leap Motion, Unity3D, etc …
Josue Yeray & Santiago Porras Charla secreta
Isabel Cabezas & Toni Recio Javascript y por qué no comparar la velocidad con el tocino
Carlos Carrillo Windows Azure Mobile Services ahora con .NET
Juan Manuel Servera Introducción a Roslyn
Miguel Egea Diseñando bases de datos relacionales para mantener históricos
Eladio Rincón Índices compuestos para desarrolladores
Fernando G. Guerrero Reflexiones sobre el futuro, de alguien que ha peleado ya algunas recesiones
Fernando Escolar Load Tests: ¿sobrevivirías al efecto menéame?
Pedro Hurtado, LLuis Franco y Sergio León Dos tontos muy tontos y un tío con futuro

¿Te lo vas a perder?

Más información

[Tips and Tricks] Comparte la pantalla de tu Windows Phone 8.1 con tu PC

Introducción

Con la Developer Preview de Windows Phone 8.1
disponible para instalar vía OTA en nuestros teléfonos, un nuevo mundo
de posibilidades se abría ante nuestros teléfonos. Entre la enorme
cantidad de novedades había una de ellas, ideal para demos y muy
solicitada, no estaba disponible, compartir la pantalla del teléfono con un PC. Pronto descubrimos que esta opción estaría disponible gracias a la llegada de una aplicación para PC.

Project My Screen App

La opción para compartir la pantalla la tenemos en la configuración del teléfono, en la opción “Project my screen”.

Sin embargo, al probar veremos que no funcionará, no encontrará nunca ningun dispositivo con el que conectar.

Sabemos que nos falta una aplicación para PC que acaba de ser liberada. La aplicación se llama Project My Screen y esta disponible para descargar en este enlace.

Compartir la pantalla

Tras instalar la aplicación “Project My Screen” y con la misma en ejecución realizamos los siguientes pasos:

  • Conectamos el teléfono al PC utilizando un cable USB.
  • Nos aparecerá en el teléfono una pantalla como la siguiente:

  • Aceptamos y… voila!

Podemos controlar el teléfono por supuesto utilizando el propio
teléfono pero también desde la aplicación, funcionan incluso los botones
de atrás, inicio y búsqueda.

NOTA: La aplicación Project My Screen se abre
por defecto en modo pantalla completa. Podemos salir de este modo
facilmente pulsando la tecla ESC.

Como véis es sumamente sencillo.

Opciones avanzadas

En las opciones de configuración de Project my screen tenemos un botón “advanced“:

Aqui podemos:

  • Mostrar en lo proyectado los gestos táctiles realizados.
  • Elegir el color con el que aparecerán los gestos.
  • Elegir la orientación del teléfono proyectado.

En caso de problemas…

Si conectas el teléfono por USB al equipo con la App “Project My
Screen” y la pantalla proyectada se mantiene en negro… tienes problemas
con los drivers, algunos antiguos estan causando problemas.

Sigue los siguientes pasos para resolver el problema:

  • Accedemos a Panel de Control>Sistema>Administrador de dispositivos.
  • Buscamos nuestro teléfono Windows Phone, hacemos clic derecho sobre el y elegimos la opción “desinstalar”.

  • Desconectamos el cable USB que conecta el teléfono con el PC.
  • En el PC vamos a Dispositivos e impresoras y elegimos la opción “Quitar dispositivo” para quitar el teléfono.
  • Volvemos a conectar por USB el teléfono al equipo.

Más información

[Eventos] //Learn/ y //Publish/

Introducción

Recientemente hemos tenido una enorme cantidad de nueva información y anuncios de múltiples tecnologías Microsoft en el //BUILD/.

Tras el //BUILD/ llegan…

//Learn/

Será un conjunto de webcasts sobre Windows Phone 8.1 organizado directamente por los MVPs de Windows Phone. Durante 6 horas
tendremos un track principal en ingles además de otros tracks en otros
idiomas como el Francés, Portugues, Chino, Ruso y como no, en Español.

En el track Español contaremos con una agenda muy completa:

  • Introducción a Windows Phone 8.1
  • Empezando a construir apps Windows XAML
  • Controles de layout y transiciones entre 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

Una agenda tan completa viene acompañada de unos ponentes de lujo como Josué Yeray, Sorey García, Roberto Alvarado, Jose Luis Latorre e Ivan Toledo. Asi que, reserva un hueco en tu agenda para el próximo 24 de Abril.
Pero cuidado, al ser un evento internacional, los horarios han tenido
que adaptarse a múltiples paises donde en España queda el comienzo para
la 1:00h del 25 de Abril. De todas formas, todo el evento será grabado y
dispondran el material para todos tras finalizar el evento.

//Publish/

Tras el //Learn/ donde se aprenden muchos conceptos básicos de la
plataforma, ¿que mejor que lanzarse de lleno?. Para ello se han
organizado hackatones donde poner en práctica todo lo aprendido.
Organizados por Microsoft y la comunidad MVP en España contaremos con
tres sedes en España:

  • Barcelona: Organizada por Microsoft.
  • Madrid: Organizada por la comunidad MVP. Se organiza el día 16 de Mayo y aquí tendre la oportunidad de estar junto a Josué Yeray y Santiago Porras para poder ayudaros en todo lo posible a crear vuestras aplicaciones.
  • Palma de Mallorca: Organizada por la comunidad MVP.

En todas las sedes tendremos grandes premios, dispositivos para que
podáis probar las aplicaciones y además no tendréis que preocuparos por
la comida, os invitamos.

¿A qué esperáis para apuntaros?

Más información