[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