[Xamarin.Forms] FormsGtkToolkit

Introducción

La llegada de nuevas plataformas siempre nos abren nuevas posibilidades. Ante la llegada del backend GTK para Xamarin.Forms podemos llegar a Linux (además de macOS y Windows). Sin embargo, también estamos ante nuevos retos y ante nuevas necesidades.

¿Cómo podemos abordar la llegada a una nueva plataforma de forma más cómoda?

Con más opciones como controles o helpers empaquetados en un Toolkit!

FormsGtkToolkit

FormsGtkToolkit una colección de clases auxiliares y controles personalizados para el backend GTK de Xamarin.Forms. Actualmente incluye:

Forms GTK Toolkit

NOTA: Pulsa en el enlace de un control específico para tener más información.

Tienes el código fuente del Toolkit disponible GitHub:

Ver GitHub

Próximamente disponible en NuGet y con más opciones. ¿Qué opinas del Toolkit?, ¿qué te gustaría ver incluido?.

Más información

[Xamarin.Forms GTK] Forms Live XAML

Introducción

La llegada de nuevas plataformas siempre nos abren nuevas posibilidades. Ante la llegada del backend GTK para Xamarin.Forms podemos llegar a Linux (además de macOS y Windows). Sin embargo, también tenemos nuevas necesidades como desarrolladores. Por ejemplo, el proceso de editar la interfaz de usuario en XAML, compilar el proyecto y ejecutar para ver el resultado en Linux.

Forms Live XAML

Para facilitar esta tarea, tenéis ahora disponible una pequeña (gran) aplicación desarrollada con Xamarin.Forms y el backend GTK que permite ver cualquier cambio de XAML al vuelo.

Live XAML desde Linux

La herramienta es muy sencilla. Cuenta con un panel lateral izquierdo donde escribir código XAML. Cualquier mínimo cambio se previsualizará en el panel de la derecha.

NOTA: También se puede forzar un refresco con el botón de actualizar situado en la parte superior derecha.

Cualquier error en XAML también será mostrado:

Detección de errores

Se soportan desde Layouts simples a aquellos más complejos (estilos, gran cantidad de líneas, etc.) con cambios al vuelo:

Cambios al vuelo

El código fuente de la herramienta esta disponible en GitHub:

Ver GitHub

La herramienta ya compilada también se encuentra disponible.

¿Qué te parece la herramienta?, ¿te resulta interesante?.

Más información

[Xamarin.Forms] Primer vistazo al backend GTK, soporte a Linux!

Introducción

Es increíble pensar que ahora puede tener una aplicación Linux nativa ejecutándose con solo algunos ajustes en una solución Xamarin.Forms.
El soporte de Linux en Xamarin.Forms ahora está en modo Preview. En este artículo, vamos a ver cómo agregar este nuevo proyecto a una solución existente de Xamarin.Forms, los obstáculos que puedes encontrar así como el estado actual y el futuro de las características de esta nueva plataforma.

Gtk# Backend

El soporte de Linux se logra con un nuevo backend basado en Gtk#. Gtk# es un Toolkit de interfaz gráfica de usuario para mono y .Net. El proyecto enlaza el kit de herramientas gtk + y una variedad de bibliotecas de GNOME, lo que permite el desarrollo de aplicaciones gráficas Gnome completamente nativas utilizando Mono y .Net.

NOTA: Este nuevo backend permite crear aplicaciones Linux, pero también aplicaciones para macOS y Windows.

Puede descargar la última versión de Gtk # desde la página de descargas del proyecto Mono.

Configurando un proyecto Linux

Desarrollar para Linux es posible desde Linux, macOS y Windows utilizando MonoDevelop, Visual Studio para macOS y Visual Studio, respectivamente.

Agregar una librería .NET desde Windows

Hasta que las plantillas de Xamarin.Forms agreguen un proyecto de aplicación Linux, podemos agregarlo fácilmente nosotros mismos. Para hacer eso en Visual Studio, agregamos un nuevo proyecto a la solución y elegimos una Biblioteca de clases.

Class Library

Agregar una librería .NET desde Linux

MonoDevelop es un entorno de desarrollo de código abierto disponible para Linux.

MonoDevelop

Para compilar librerías portables (PCL) desde MonoDevelop, es necesario el siguiente comando:

sudo apt-get install referenceassemblies-pcl

Para crear un nuevo proyecto de tipo librería .NET en MonoDevelop, se debe elegir la opción una Biblioteca de clases.

Desde Linux

Y desde macOS

Para crear un nuevo proyecto de biblioteca .NET en Visual Studio para macOS, agregamos un nuevo proyecto a la solución y elegimos una Biblioteca de clases.

Librería desde macOS

Configurar el proyecto

Lo primero que tenemos que hacer para trabajar con el backend Gtk es precisamente agregar al proyecto recién creado las referencias a las bibliotecas Gtk#.

Referencias a Gtk#

También necesitaremos agregar el último paquete Preview de Xamarin.Forms (Nightly).
Editamos  la clase creada con la librería:

public class Program
{
        [STAThread]
        static void Main(string[] args)
        {
            Gtk.Application.Init();
            Forms.Init();
            var app = new App();
            var window = new FormsWindow();
            window.LoadApplication(app);
            window.SetApplicationTitle("WeatherApp");
            window.Show();
            Gtk.Application.Run();
        } 
}

Inicializa Xamarin.Forms, crea una ventana y carga la aplicación Forms.

NOTA: Si tienes otras dependencias que deben inicializarse, aquí puedes hacerlo.

A probar!

Con el proyecto del backend Gtk como proyecto de inicio, ejecútalo (F5). Voila! ¡Ahora tiene una aplicación Gtk nativa!

Voila!

¿Algo más?

Ahora que tienes una aplicación, es hora de ponerse la gorra de diseñador de UX y comenzar a explorar los cambios necesarios para adaptar la aplicación a esta nueva plataforma.

Estilos

Échale un vistazo al estilo de la interfaz de usuario para Linux. Es posible que el mismo estilo utilizado en los dispositivos móviles no se vea bien. ¡Esto lo cambios fácilmente!
Con los cambios recientes realizados en OnPlatform, ahora puede seleccionar cada plataforma. Eso incluye a GTK.

Desde XAML:

<Button.TextColor>
     <OnPlatform x:TypeArguments="Color">
           <On Platform="iOS" Value="White"/>
           <On Platform="GTK" Value="White"/>
           <On Platform="Android" Value="Black"/>
     </OnPlatform>
</Button.TextColor>

O desde C#:

if (Device.RuntimePlatform == Device.GTK)
     return "Images/image.jpg";
else if (Device.RuntimePlatform == Device.UWP)
     return "Assets/image.jpg";
else
     return "image.jpg";

Temas Gtk#

Hay una gran variedad de temas disponibles para GTK. ¡Se pueden usar desde la aplicación Xamarin.Forms!

GtkThemes.Init();
GtkThemes.LoadCustomTheme("Themes/gtkrc");

Nombre e icono de la aplicación

Para representar la imagen de la aplicación, es importante establecer su título e icono.

window.SetApplicationTitle("WeatherApp");
window.SetApplicationIcon("icon.png")

Forms Embedding

La posibilidad de tomar cualquier ContentPage y usarlo en aplicaciones nativas, ¡también está disponible en el backend de Gtk!

var settingsView = new SettingsView().CreateContainer();
vbox.PackEnd(settingsView, true, true, 0);

Tienes un ejemplo disponible en GitHub:

Ver GitHub

Recuerda, es una Preview…

Esta Preview tiene un soporte muy alto de las características y opciones de Xamarin.Forms. Sin embargo, hay algunas características aun no disponibles:

  • Pinch Gesture
  • RotationX
  • RotationY
  • Scale
  • Swipe Gesture

Ejemplos, ejemplos, ejemplos!

Un nuevo backend ofrece la posibilidad de llegar a nuevas plataformas, es normal querer probar todas las posibilidades. ¡No te preocupes, vamos a ver varios ejemplos!

Movies es una aplicación Xamarin.Forms disponible para Linux que hace uso de The Movie Database (TMDb) API, una popular base de datos de películas y series de TV, para demostrar las posibilidades del nuevo backend haciendo uso de una gran variedad de funcionalidades ( mapas, WebView, temas gtk, etc.).

Movies

Disponible en GitHub:

Ver GitHub

Weather es otro ejemplo de aplicación Xamarin.Forms con soporte a Linux. Es una aplicación para ver la información meteorológica de forma muy visual.

Weather

Disponible en GitHub:

Ver GitHub

Nuevas posibilidades

Linux se ejecuta bajo una gran variedad de dispositivos. Xamarin.IoT permite a los desarrolladores escribir y compartir código C# en dispositivos IoT tales como Raspberry Pi e Intel Edison. Funciona con cualquier dispositivo IoT que ejecute Linux (distribuciones más populares) y se integra sin problemas con Azure IoT Suite para conectar, analizar y asegurar soluciones de IoT.

Xamarin.IoT

Podemos combinar Xamarin.Forms con Xamarin.IoT!. Se puede crear la interfaz de usuario de la aplicación con XAML o C# usando Xamarin.Forms y acceder a los sensores usando Xamarin.IoT.

Puedes encontrar un ejemplo de la aplicación WeatherApp que accede a la información de un sensor de humedad en GitHub: Ver GitHub

[Xamarin.Forms] Usando Lottie

Introducción

Día a día vamos viendo la evolución de las aplicaciones móviles. Actualmente, la mayoría de usuarios estan acostumbrados a utilizar aplicaciones visualmente atractivas que hacen uso de diferentes transiciones, efectos y animaciones.

En Xamarin.Forms contamos con API compartida para la gestión de animaciones que además da pie a crear librerías como Xamanimation. Sin embargo, en ocasiones crear algunas animaciones (diferentes pasos, transformaciones, etc.) es complejo.

Lottie

¿Te imaginas tomar una animación creada por un diseñador y poder utilizarla?.

Lottie es una librería de animaciones creada por Airbnb para iOS y Android que se encarga de tomar animaciones de After Effect exportadas en JSON y renderizarla utilizando APIs de animación nativa en cada plataforma.

Lottie

Las animaciones pueden ser extremadamente complejas pero al final, trabajamos con archivos de imagen y JSONs lo que se traduce en un requisito pequeño en tamaño otorgando unas posibilidades altas. Las animaciones se pueden reproducir, pausar, detener, jugar con la velocidad o cambiar la escala.

Obtener recursos

Un gran fuente de animaciones es LottieFiles. Puedes encontrar una gran variedad de animaciones listas para utilizar con opciones de búsqueda, etc.

LottieFiles

NOTA: Si usas animaciones de LottieFiles, recuerda otorgar crédito a sus creadores.

Lottie & Xamarin.Forms

La librería Lottie fue creada por Airbnb inicialmente para iOS, Android y React Native. Sin embargo, gracias a la contrinución de Martijn van Dijk y otros miembros de la comuidad, tenemos soporte en Xamarin y Xamarin.Forms.

Para comenzar a trabajar con Lottie en Xamarin.Forms utilizaremos el paquete NuGet Aribnb.Xamarin.Forms.Lottie:

Install-Package Com.Airbnb.Xamarin.Forms.Lottie

NOTA: En UWP utilizaremos el paquete Lottie.UWP.

Para completar el proceso de preparación de Lottie en nuestro proyecto Xamarin.Forms, necesitamos añadir la siguiente línea tras la inicialización de Xamarin.Forms en cada proyecto nativo:

AnimationViewRenderer.Init();

Todo listo!.

Para poder mostrar una animación de Lottie, debemos contar con ella. En nuestro ejemplo vamos a utilizar esta animación disponible en LottieFiles creada por Salatiel Queiroz.

Tras descargar el archivo JSON, vamos a añadirlo en cada proyecto nativo:

  • Android: En la carpeta Assets. El archivo debe tener como acción de compilación AndroidAsset.
  • iOS: En la carpeta Resources. El archivo debe tener como acción de compilación BundleResource.
  • UWP: En la carpeta Assets (o en la raíz), el archivo debe tener como acción de compilación Content.

Para mostrar la animación necesitamos un elemento visual que nos permita además realizar una gestión de la misma. Este elemento visual es AnimationView.

Las propiedades fundamentales del elemento visual son:

  • Animation: El archivo JSON a utilizar.
  • Loop: Un booleano que indica si la animación se repite en bucle o no.
  • AutoPlay: Booleano que determina si la animación se auto reproduce.
  • IsPlaying: Indica si la animación se esta reproduciendo o no.
  • Speed: Determina la velocidad de reproducción de la animación.
  • Progress: Valor numérico que nos indica el progreso actual de la animación en reproducción.

Los eventos:

  • OnPlay: Se inicia la animación.
  • OnPause: Pausa.
  • OnFinish: Fin de la animación.

Comandos:

  • PlaybackStartedCommand: Comanzo lanzado cuando se inicia la animación.
  • PlaybackFinishedCommand: Comando lanzado al completar la animación.

Para utilizar AnimationView desde XAML necesitamos utilizar el siguiente espacio de nombres:

xmlns:lottie="clr-namespace:Lottie.Forms;assembly=Lottie.Forms"

La interfaz:

<lottie:AnimationView
     x:Name="LottieView" 
     Animation="Tadah.json" 
     Loop="False" 
     AutoPlay="True"
     PlaybackStartedCommand="{Binding PlayingCommand}"
     PlaybackFinishedCommand="{Binding FinishedCommand}"
     VerticalOptions="FillAndExpand"
     HorizontalOptions="FillAndExpand" />

Podemos pausar la animación utilizando el método Pause y lanzar la animación con Play.

El resultado:

El resultado

Como podemos observar, el resultado es increíble. Con diferentes recursos y aplicando diferentes animaciones de rotación, trasladación, etc. podríamos conseguir resultados similares pero con un esfuerzo mucho más elevado.

Ejemplo disponible en GitHub:

Ver GitHub

Recordar que podéis dejar en los comentarios cualquier tipo de sugerencia o pregunta.

Más información

[Xamarin.Forms] Aplicaciones WPF

Introducción

El soporte de WPF en Xamarin.Forms ahora está  disponible en la Nightly (paquetes previos) de Xamarin.Forms. En este artículo, vamos a ver cómo agregar este nuevo proyecto a una solución existente de Xamarin.Forms, los obstáculos que puedes encontrar así como el estado actual y el futuro de las características de esta nueva plataforma.

Backend WPF

WPF es la abreviación de Windows Presentation Foundation. Hablamos de un conjunto de APIs destinadas a crear interfaces de usuario enriquecidas para Windows.

Cabe destacar que se soporta Windows Vista hasta Windows 10.

Crear nuevo proyecto

Tras crear un nuevo proyecto Xamarin.Forms con una librería NET Standard.

New Cross Platform App

A continuación, vamos a añadir un proyecto WPF. Dentro de la categoría escritorio clássico de Windows, elegimos la opción Aplicación de WPF:

Nueva App WPF

A continuación, vamos a actualizar el paquete de Xamarin.Forms para utilizar la última Nightly (donde ya se incluye la Preview de WPF).

Debemos añadir https://www.myget.org/F/xamarinforms-ci/api/v2 como origen de paquetes NuGet (Herramientas > Opciones > Administrador de paquetes NuGet).

Y actualizamos Xamarin.Forms además de instalar el paquete en todos los proyectos:

Xamarin.Forms Nightly

A continuación, vamos a instalar el paquete Xamarin.Forms.Platform.WPF en el proyecto WPF. Este paquete es el que cuenta con las implementaciones necesarias de Xamarin.Forms en WPF.

Xamarin.Forms.Platform.WPF

Todo listo a nivel de dependencias. Es hora de cambiar levemente el código para inicializar Forms.

En el archivo App.xaml vamos a añadir algunos recursos utilizados por el backend WPF:

<Application.Resources>
 <ResourceDictionary>
 <ResourceDictionary.MergedDictionaries>
 <ResourceDictionary Source="/WPFLightToolkit;component/Assets/Default.xaml" />
 </ResourceDictionary.MergedDictionaries>

<!-- Default Global Color -->
 <SolidColorBrush x:Key="WindowBackgroundColor" Color="White" />
 <SolidColorBrush x:Key="AccentColor" Color="#3498db" />

     <!-- Default Command Bar Color -->
     <SolidColorBrush x:Key="CommandBarBackgroundColor" Color="#3498db" />
     <SolidColorBrush x:Key="CommandBarTextColor" Color="White" />

     <!-- Default Title Bar Color -->
     <SolidColorBrush x:Key="DefaultTitleBarBackgroundColor" Color="#3498db" />
     <SolidColorBrush x:Key="DefaultTitleBarTextColor" Color="White" />

     <!-- Default Tabbed Bar Color -->
     <SolidColorBrush x:Key="DefaultTabbedBarBackgroundColor" Color="#3498db" />
     <SolidColorBrush x:Key="DefaultTabbedBarTextColor" Color="White" />

     </ResourceDictionary>
</Application.Resources>

Actualizamos la ventana principal, MainWindow.xaml para utilizar FormsApplicationPage:

<wpf:FormsApplicationPage x:Class="WPFSample.WPF.MainWindow"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:wpf="clr-namespace:Xamarin.Forms.Platform.WPF;assembly=Xamarin.Forms.Platform.WPF"
     mc:Ignorable="d"
     Title="MainWindow" Height="350" Width="525">
     <Grid>
 
     </Grid>
</wpf:FormsApplicationPage>

También actualizaremos el tipo del code behind en MainWindow.xaml.cs:

using Xamarin.Forms.Platform.WPF;

namespace WPFSample.WPF
{
     public partial class MainWindow : FormsApplicationPage
     {
          public MainWindow()
          {
               InitializeComponent();
          }
     }
}

Todo listo, ejecutamos!

Hola WPF!

Más ejemplos!

Un nuevo backend ofrece la posibilidad de llegar a nuevas plataformas, es normal querer probar todas las posibilidades. ¡No te preocupes, vamos a ver más ejemplos!

WeatherApp es otro ejemplo de aplicación Xamarin.Forms con soporte a WPF. Es una aplicación para ver la información meteorológica de forma muy visual.

WeatherApp

Disponible en GitHub:

Ver GitHub

Native Embedding

La posibilidad de tomar cualquier ContentPage y usarlo en aplicaciones nativas, ¡también está disponible en el backend de WPF!

var settingsView = new SettingsView().CreateContainer();
vbox.PackEnd(settingsView, true, true, 0);

El resultado:

Native Embedding

Tienes un ejemplo disponible en GitHub:

Ver GitHub

¿Algo más?

Ahora que tienes una aplicación, es hora de ponerse la gorra de diseñador de UX y comenzar a explorar los cambios necesarios para adaptar la aplicación a esta nueva plataforma.

Estilos

Échale un vistazo al estilo de la interfaz de usuario para Linux. Es posible que el mismo estilo utilizado en los dispositivos móviles no se vea bien. ¡Esto lo cambios fácilmente!
Con los cambios recientes realizados en OnPlatform, ahora puede seleccionar cada plataforma. Eso incluye a WPF.

Desde XAML:

<Button.TextColor>
     <OnPlatform x:TypeArguments="Color">
           <On Platform="iOS" Value="White"/>
           <On Platform="WPF" Value="White"/>
           <On Platform="Android" Value="Black"/>
     </OnPlatform>
</Button.TextColor>

O desde C#:

if (Device.RuntimePlatform == Device.WPF)
     return "Images/image.jpg";
else if (Device.RuntimePlatform == Device.UWP)
     return "Assets/image.jpg";
else
     return "image.jpg";

Recuerda, es una Preview…

Esta Preview tiene un soporte muy alto de las características y opciones de Xamarin.Forms. Sin embargo, hay algunas características aun no disponibles:

  • Accessibility
  • List (mucho trabajo pendiente aún)
  • NativeViewWrapper
  • NavigationMenu
  • TimePicker

Más información

[Xamarin.Forms] Estilos con CSS

Introducción

En toda aplicación móvil la apariencia visual es vital. Cada vez es mayor el esfuerzo depositado a la hora de crear aplicaciones atractivas a la par que intuitivas y en muchos casos conseguir una imagen única que diferencia a la Aplicación del resto es prioritario. Por este motivo, debemos de contar con opciones sencillas de poder personalizar los distintos elementos que componen la interfaz.

Los estilos permitir definir múltiples propiedades visuales de elementos de la interfaz de forma reutilizable.

Hasta ahora, podíamos utilizar C# o XAML para definir estilos. También tenemos la posibilidad de utilizar diferentes diccionarios de recursos entre otras opciones. Ahora, con la llegada de la última versión nightly de Xamarin.Forms, se incluye soporte a definir los estilos utilizando CSS.

NOTA: Puedes ver el conjunto de opciones soportadas en esta Pull Request de Stephane Delcroix.

En este artículo, vamos a conocer las opciones disponibles utilizando CSS para definir estilos.

Estilos utilizando CSS

Vamos a crear un nuevo proyecto Xamarin.Forms utilizando una librería NET Standard. Tras crear el proyecto, actualizamos Xamarin.Forms a su última versión nightly disponible (2.6.0.52014-nightly al momento de escribir este artículo).

Xamarin.Forms Nightly

NOTA: Para tener acceso a las versiones nightly de Xamarin.Forms es necesario añadir https://www.myget.org/F/xamarinforms-ci/api/v2 como origen de paquetes.

Crear un Stylesheet

Los estilos los aplicaremos utilizando CSS, para ello debemos crear archivo/s CSS. Puedes crear estos archivos en la librería NET Standard en cualquier localización aunque la recomendación sería mantener todos los estilos manteniendo una estructura de carpetas que ayude a mantener el proyecto con facilidad. En nuestro ejemplo, creamos una carpeta llamada Styles y dentro un archivo MainView.css donde aplicaremos los estilos a utilizar en la vista principal de la aplicación.

Es importante recordar que se debe establecer la propiedad Build Action del archivo CSS a EmbeddedResource.

Tras crear el archivo, desde la ContentPage:

<ContentPage.Resources>
 <StyleSheet Source="../Styles/MainView.css" />
</ContentPage.Resources>

De esta forma, podemos acceder a los estilos CSS desde la ContentPage.

Opciones soportadas (selectores y propiedades)

Los selectores en CSS son imprescindibles para poder aplicar los estilos. El selector es quien determina a que elemento hay que aplicar el estilo.

Los mismos selectores utilizados en CSS se utilizan en este caso en Xamarin.Forms salvo una excepción, ^base , que solo aplica en Xamarin.Forms.

Selector Ejemplo Descripción
.class .header Selecciona todos los elementos con la propiedad StyleClass que contiene ‘header’.
#id #email Selecciona todos los elementos con StyleId establecido a email.
* * Secciona todos los elementos.
element label Selecciona todos los elementos de tipo Label.
^base ^contentpage Selecciona todos los elementos con ContentPage como clase base, esto incluye a la propia ContentPage. Este selector no esta presente en la especificación CSS y solo aplica a Xamarin.Forms.
element,element label,button Selecciona todos los Buttons y todos los Labels.
element element stacklayout label Selecciona todos los Labels dentro de un StackLayout.
element>element stacklayout>label Selecciona todos los Labels con un StackLayout como padre directo.
element+element label+entry Selecciona todos los Entries que están directamente tras un Label.
element~element label~entry Selecciona todos los Entries precedidos por un Label.

Se pueden realizar combinaciones de diferentes selectores lo que nos otorga grandes posibilidades de forma muy simple. Ejemplo:

StackLayout > ContentView > label.email

El resto de selectores que no aparecen en la tabla no estan soportados por ahora (Ejemplo: @media o @supports).

Pasamos a ver el listado de propiedades soportadas:

Propiedad Aplica a
background-color VisualElement
background-image Page
border-color ButtonFrame
border-width Button
color ButtonDatePickerEditorEntryLabelPicker

SearchBarTimePicker

direction VisualElement
font-family ButtonDatePickerEditorEntryLabelPicker,

SearchBarTimePickerSpan

font-size ButtonDatePickerEditorEntryLabelPicker

SearchBarTimePickerSpan

font-style ButtonDatePickerEditorEntryLabelPicker

SearchBarTimePickerSpan

height VisualElement
margin View
margin-left View
margin-top View
margin-right View
margin-bottom View
min-height VisualElement
min-width VisualElement
opacity VisualElement
padding LayoutPage
padding-left LayoutPage
padding-top LayoutPage
padding-right LayoutPage
padding-bottom LayoutPage
text-align EntryEntryCellLabelSearchBar
visibility VisualElement
width VisualElement

Se soportan diferentes formatos de colores (RGB, RGBA, Hex, HSL, etc) y propiedades de Thickness con el mismo formato que en XAML.

Aplicando estilos en XAML

Tras ver el conjunto de selectores y propiedades soportadas, podemos aplicar estilos.

El estilo:

.CSSButton {
     background-color: #11313F;
     color: white;
     font-size: 16;
     height: 60;
     border: 0;
}

Utilizar el estilo:

<Button
     Text="CSS Style Button"
     StyleClass="CSSButton" />

Con StyleClass buscamos el estilo definido por un selector de tipo .class.

Ejemplo disponible en GitHub:

Ver GitHub

Es importante recordar que, la posibilidad de aplicar estilos utilizando CSS es un añadido. No llega para reemplazar la posibilidad de estilos con XAML (en estos momentos, aplicar estilos con XAML o C# cuenta con más características).

El aplicar estilos con CSS cuenta con ciertos beneficios como la flexibilidad aportada por los selectores además de reducir la verbosidad de XAML. Además, hoy día, la mayoría de herramientas de diseño (como Sketch) cuentan con la posibilidad de facilitar los estilos en CSS.

¿Qué te parece esta nueva característica?. Recordar que podéis dejar en los comentarios cualquier tipo de sugerencia o pregunta.

Más información

[Xamarin.Forms] Uso de SQLite, múltiples tablas, relaciones y operaciones en cascada

Introducción

El trabajo con datos en dispositivos móviles se ha convertido ya en algo común y habitual en el desarrollo de aplicaciones. Existe una gran variedad de tipos de datos y formas de almacenamiento:

  • Archivos de texto. Texto plano o html cacheado en el espacio de almacenamiento aislado de la aplicación.
  • Imágenes. En el espacio de almacenamiento aislado de la aplicación o almacenadas en directorios conocidos del sistema.
  • Archivos serializados. Archivos XML o Json con objetos serializados.
  • Bases de datos. Cuando se requieren datos estructurados, obtener información más compleja con consultas avanzadas entre otro tipo de necesidades, la posibilidad de las bases de datos es la elección idónea.

Las ventajas de utilizar una base de datos son múltiples:

  • Almacenamiento estructurado con eficacia alta.
  • Posibilidad de utilizar consultas y aplicar filtros.
  • Posibilidad de reutilizar conocimientos de base de datos en la gestión de datos en nuestras aplicaciones móviles.

Introducción a SQLite

SQLite es un motor de base de datos Open Source utilizado en todas las plataformas móviles y adoptado tanto por Apple como Google como Microsoft. El uso de SQLite en aplicaciones móviles es una gran opción ya que:

  • La base de datos es pequeña y fácil de portar.
  • La base de datos se concentra en un pequeño archivo.
  • Implementa la mayor parte del estándar SQL92.

Arrancamos el proyecto

Comenzamos creando una aplicación Xamarin.Forms utilizando una librería NET Standard:

Nueva aplicación Xamarin.Forms usando Net Standard

Tras crear la aplicación, añadimos las carpetas básicas para aplicar el patrón MVVM además del paquete NuGet de Autofac para la gestión del contenedor de dependencias.

Estructura del proyecto

Con el proyecto y estructura base creada, vamos a añadir SQLite al proyecto. Para ello, vamos a usar NuGet. Vamos a añadir en cada proyecto de la solución la última versión disponible del paquete utilizando NuGet. El paquete a utilizar es sql-net-pcl, implementación Open Source con soporte a .NET.

sqlite-net-pcl

Tras añadir la referencia vamos a crear una interfaz que defina como obtener la conexión con la base de datos y abstraer la funcionalidad específica de cada plataforma. Trabajando con SQLite, el único trabajo específico a implementar en cada plataforma es determinar la ruta a la base de datos.

public interface IPathService
{
     string GetDatabasePath();
}

En Android, la implementación de IPathService nos permite obtener la ruta a la base de datos.

[assembly: Dependency(typeof(PathService))]
namespace TodoSqlite.Droid.Services.Sqlite
{
     public class PathService : IPathService
     {
          public string GetDatabasePath()
          {
               string path = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
               return Path.Combine(path, AppSettings.DatabaseName);
          }
     }
}

NOTA: Utilizamos el atributo assembly:Dependency para poder realizar la resolución de la implementación con DependencyService.

En iOS:

[assembly: Dependency(typeof(PathService))]
namespace TodoSqlite.iOS.Services.Sqlite
{
     public class PathService : IPathService
     {
          public string GetDatabasePath()
          {
                string docFolder = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
                string libFolder = Path.Combine(docFolder, "..", "Library", "Databases");

                if (!Directory.Exists(libFolder))
                {
                     Directory.CreateDirectory(libFolder);
                }

                return Path.Combine(libFolder, AppSettings.DatabaseName);
          }
     }
}

El archivo de la base de datos lo situamos dentro de la carpeta Library dentro del espacio de almacenamiento de la aplicación.

Y en UWP:

[assembly: Dependency(typeof(PathService))]
namespace TodoSqlite.UWP.Services.Sqlite
{
     public class PathService : IPathService
     {
          public string GetDatabasePath()
          {
               return Path.Combine(ApplicationData.Current.LocalFolder.Path, AppSettings.DatabaseName);
          }
     }
}

Todo listo para comenzar!

La definición de modelos

En nuestra aplicación, trabajaremos con elementos del listado ToDo, una única entidad sencilla.

public class TodoItem
{
     [PrimaryKey, AutoIncrement]
     public int Id { get; set; }
     public string Name { get; set; }
     public string Notes { get; set; }
     public bool Done { get; set; }
}

La gestión de campos especiales o relacionados las gestionamos mediante el uso de etiquetas. En nuestro ejemplo establecemos el campo Id como clave primaria gracias a la etiqueta PrimaryKey y además que autoincremente con el uso de AutoIncrement.

Trabajando con SQLite

Para trabajar con la base de datos utilizaremos DependencyService para obtener la implementación de IPathService y obtener la ruta a la base de datos en cada plataforma.

var databasePath = DependencyService.Get<IPathService>().GetDatabasePath();

Con la ruta de la base de datos, creamos una conexión:

var sqlCon = new SQLiteAsyncConnection(databasePath);

Comenzamos creando la tabla necesaria en la base de datos.

await _sqlCon.CreateTableAsync<TodoItem>().ConfigureAwait(false);

Continuamos con las operaciones básicas de CRUD. Para obtener la información almacenada en una tabla podemos acceder a la tabla y obtener el listado utilizando el método ToListAsync.

public async Task<IList<TodoItem>> GetAll()
{
     var items = new List<TodoItem>();
     using (await Mutex.LockAsync().ConfigureAwait(false))
     {
          items = await _sqlCon.Table<TodoItem>().ToListAsync().ConfigureAwait(false);
     }

     return items;
}

NOTA: Podemos realizar consultar SQL utilizando el método QueryAync.

A la hora de insertar, verificamos si estamos ante un registro existente o no, para realizar el registro de un nuevo elemento o actualizar uno existente con los métodos InsertAsync o UpdateAsync respectivamente.

public async Task Insert(TodoItem item)
{
      using (await Mutex.LockAsync().ConfigureAwait(false))
      {
           var existingTodoItem = await _sqlCon.Table<TodoItem>()
           .Where(x => x.Id == item.Id)
           .FirstOrDefaultAsync();

          if (existingTodoItem == null)
          {
               await _sqlCon.InsertAsync(item).ConfigureAwait(false);
          }
          else
          {
               item.Id = existingTodoItem.Id;
               await _sqlCon.UpdateAsync(item).ConfigureAwait(false);
          }
     }
}

Eliminar es una acción sencilla realizada con el método DeleteAsync.

await _sqlCon.DeleteAsync(item);

El resultado del ejemplo:

Tenéis el código fuente disponible e GitHub:

Ver GitHub

Múltiples tablas

Con lo visto hasta aquí, tenemos suficiente para gestionar una base de datos local en Android, iOS y Windows. Sin embargo, ¿cómo hacemos relaciones entre diferentes tablas?, ¿y operaciones en cascada que afecten a múltiples tablas a la vez?.

Con sqlite-net-pcl, podemos trabajar con diferentes tablas y realizar relaciones. Veamos un ejemplo:

public class Stock 
{ 
     [PrimaryKey, AutoIncrement] 
     public int Id { get; set; } 
     public string Symbol { get; set; } 
} 
 
public class Valuation 
{ 
     [PrimaryKey, AutoIncrement] 
     public int Id { get; set; } 
     [Indexed] 
     public int StockId { get; set; } 
     public DateTime Time { get; set; } 
     public decimal Price { get; set; } 
}

Es importante resaltar el uso de atributo Indexed. Estamos asociando las tablas Valuation y Stock.

Creamos ambas tablas utilizando el método CreateTable por cada tabla:

db.CreateTable<Stock>();       
db.CreateTable<Valuation>();

Y obtenemos la información relacionada con ambas tablas gracias al uso de queries:

return db.Query<Valuation> ("select * from Valuation where StockId = ?", stock.Id);

De esta forma obtendríamos los registros de la tabla Valuation dado un SotckId específico.

Esta es una forma simple de trabajar. Sin embargo, existe un wrapper de SQLite.NET llamado SQLite-Net Extensions que amplía funcionalidades como permitir gestionar relaciones (uno a uno, uno a varios, varios a uno y varios a varios), operaciones en cascada además de otras opciones interesantes de forma muy sencilla.

Vamos a regresar a nuestra aplicación de tareas. Para aprender como gestionar más de una tabla, vamos a añadir una segunda tabla de pasos en las tareas. De modo que, una tarea tendrá N pasos.

Veamos la creación de las tablas. Creamos una segunda tabla (recuerda, una clase) llamada Step:

[Table("Steps")]
public class Step
{
     [PrimaryKey, AutoIncrement]
     public int Id { get; set; }

     public string Name { get; set; }

     [ForeignKey(typeof(TodoItem))]
     public int WorkerId { get; set; }
}

Al crear directamente la definición, vamos a especificar relaciones entre tablas. En este caso, destacamos una propiedad que será la ForeignKey de la tabla TodoItem.

[Table("TodoItems")]
public class TodoItem
{
     [PrimaryKey, AutoIncrement]
     public int Id { get; set; }
     public string Name { get; set; }
     public string Notes { get; set; }
     public bool Done { get; set; }
     [OneToMany(CascadeOperations = CascadeOperation.CascadeInsert)]
     public List<Step> Steps { get; set; }
}

Gracias a las extensiones aportadas, podemos definir directamente la relación entre las tablas TodoItems y Steps. En este caso será un OneToMany. Por defecto, las operaciones no son recursivas. Podemos modificar este compartamiento estableciendo operaciones en cascada. En nuestro caso, usaremos CascadeOperations para establecer el insertar registros en cascada (al registrar un nuevo TodoItem, registraremos también sus Steps).

Para crear ambas tablas, al igual que con sqlite-net-pcl, utilizamos el método CreateTableAsync:

await _sqlCon.CreateTableAsync<Step>(CreateFlags.None).ConfigureAwait(false);
await _sqlCon.CreateTableAsync<TodoItem>(CreateFlags.None).ConfigureAwait(false);

Operaciones en cascada

A la hora de insertar registros, contamos con diferentes métodos en las extensiones de SQLite:

  • InsertWithChildren
  • InserOrReplaceWithChildren
  • InserAllWithChildren
  • InsertOrReplaceAllWithChildren

Su uso dependerá de si vamos a insertar o reemplazar y del número de registros.

NOTA: De cada método existe una version asíncrona.

await _sqlCon.InsertWithChildrenAsync(item, recursive: true).ConfigureAwait(false);

También existen otras opciones interesantes como:

  • Actualizar en cascada.
  • Eliminar en cascada.
  • Propiedades sólo de lectura.
  • Diferentes tipos de relaciones y relaciones inversas.
  • Etc.

Tenéis el código fuente disponible e GitHub:

Ver GitHub

Recordad que podéis dejar cualquier comentario, sugerencia o duda en los comentarios.

Más información

Utilizando agente macOS Hosted para compilar iOS en VSTS

Introducción

Visual Studio Team Services paso a paso ha logrado tener un sistema de builds sencillo de configurar / utilizar y sobretodo muy completo.

Recientemente se añadieron máquinas Hosted Linux que venían a sumarse a las opciones ya disponibles con Windows. Ahora llega el turno de macOS!.

Agente macOS Hosted

Al crear la Build para un proyecto iOS, tenemos disponible una plantilla Xamarin.iOS practicamente preparada. Tras seleccionar la plantilla Xamarin.iOS, llega la hora de seleccionar agente…

Hosted macOS Preview

Y ahora tenemos la opción Hosted macOS Preview!

En el momento de escribir este artículo, las máquinas macOS cuentan con OS X 10.12.6 y todo lo necesario para compilar, no solo proyectos iOS, también Android, etc. Puedes ver un listado completo de contenido preparado e instalado en la máquina macOS en este enlace.

 

Build

¿Personalizar versión herramientas utilizadas?

Podemos seleccionar manualmente la versión a utilizar del SDK de Xamarin. Para ello, antes del paso de compilación, es necesario ejecutar una línea de comandos donde vamos a establecer la versión de Mono asociada con el SDK de Xamarin. Veamos un ejemplo:

/bin/bash –c "sudo $AGENT_HOMEDIRECTORY/scripts/select-xamarin-sdk.sh 5_4_1"

En el caso anterior se selecciona la versión 5.4.2 (se reemplazan . por _). Puedes ver las versiones a elegir en este enlace.

Si utilizas XCode, quizás también te intere seleccionar la versión. Para hacerlo, antes del paso xcodebuild, se debe ejecutar el siguiente comando:

/bin/bash –c "sudo xcode-select -s /Applications/Xcode_8.3.3.app/Contents/Developer"

Las versiones de XCode que se pueden utilizar se pueden ver en este enlace.

Más información

[Codemotion 2017] Taller de Xamarin

Codemotion 2017

Otro año más, Codemotion se celebrará en Madrid los días 24 y 25 de noviembre en el Campus de Montepríncipe de la Universidad CEU San Pablo. Como en años anteriores, es una cita imprescindible para el mundo del desarrollo de software.

Codemotion 2017

Taller Xamarin

Este año volveré a tener la oportunidad de participar en el evento aunque a diferencia de años anteriores, donde participé con sesiones técnicas, estaré con un taller.

El Sábado 25 de Noviembre, de 12:15h a 14:00h tendremos un taller de desarrollo de aplicaciones multiplataforma con Xamarin. En este Lab veremos como desarrollar aplicaciones nativas multiplataforma para iOS, Android, Windows, macOS y Linux compartiendo la mayor cantidad de código posible utilizando Xamarin.Forms.

Requisitos:

  • Visual Studio 2015 o 2017 para Windows (la versión Community es perfectamente válida) o Visual Studio para macOS.
  • Asegúrate de tener instalado Xamarin.
  • Emuladores de Android.
  • Muchas ganas!

Material:

¿Nos vemos allí?

Más información

[Xamarin.Forms] Utilizando MvvmCross

Introducción

A la hora de desarrollar aplicaciones multiplataforma con Xamarin una de las arquitecturas más utilizadas sin duda alguna es MVVM. Para realizar la implementación contamos con diferentes opciones y algunos frameworks como MvvmCross, una de las opciones más utilizadas con Xamarin Classic.

Tras recibir diferente feedback, muchos tienen la duda…¿y con Xamarin.Forms?.

En este artículo vamos a ver como utilizar MvvmCross con Xamarin.Forms tanto para acciones básicas como asociar vistas con viewmodels así como realizar la navegación entre páginas o el uso de plugins.

¿Lo vemos?

MVVM

Model-View-ViewModel (MVVM) es un patrón de diseño de aplicaciones que permite desacoplar el código de interfaz de usuario del código que no sea de interfaz de usuario.

El patrón MVVM consta de 3 partes:

  • La vista (View) contiene la interfaz de usuario y su lógica.
  • El vista-modelo (ViewModel) contiene la lógica de presentación.
  • El modelo (Model) contiene la lógica de negocio junto a los datos.

La vista interactúa con el vista-modelo mediante enlace a datos (Data Binding) y mediante comandos:

Las ventajas conseguidas utilizando el patrón son significativas:

  • Nos permite dividir el trabajo de manera muy sencilla (diseñadores – desarrolladores)
  • El mantenimiento es más sencillo.
  • Permite realizar Test a nuestro código.
  • Permite una más fácil reutilización de código.

MvvmCross

MvvmCross es un framework que permite aplicar el patrón MVVM, totalmente centrado en Xamarin y el ecosistema móvil. Cuenta con una serie de opciones destinadas a resolver algunas de las necesidades más comunes en el desarrollo móvil además de una gran comunidad que aporta mejoras tanto al propio framework como una diversidad amplia de plugins.

MvvmCross

MvvmCross soporta una gran variedad de plataformas. En el caso de Xamarin.Forms se soporta:

  • PCL
  • Android
  • iOS
  • UWP

En el futuro, al pasar releases estables, se añadirán otras plataformas como Linux (Gtk) o Tizen.

Utilizar MvvmCross en Xamarin.Forms

MvvmCross cuenta con una serie de paquetes NuGet que nos facilitan muchísimo la integración con Xamarin.Forms. Hablamos de los paquetes StarterPack que se encargará de añadir tanto las librerías básicas necesarias como los archivos que nos permitirán utilizar MvvmCross en cada plataforma y de MvvmCross.Forms.

NOTA: A la hora de escribir este artículo, utilizamos la versión 5.4.2 de MvvmCross.

Tras añadir ambos paquetes a todos los proyectos de la solución, comenzamos a editar cada proyecto.

PCL

Comenzamos modificando la aplicación Xamarin.Forms. Para ello, cambiamos:

<FormsApplication xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="HelloMvxForms.Core.App">

</FormsApplication>

Por:

<?xml version="1.0" encoding="utf-8" ?>
<mvx:MvxFormsApplication 
     xmlns="http://xamarin.com/schemas/2014/forms"
     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
     xmlns:mvx="clr-namespace:MvvmCross.Forms.Platform;assembly=MvvmCross.Forms"
     x:Class="HelloMvxForms.Core.App">
</mvx:MvxFormsApplication>

Igualmente, cambiamos App.xaml.cs:

public partial class App : FormsApplication

Por:

public partial class App : MvxFormsApplication

En esta misma clase, vamos a eliminarla línea encargada de estableder la MainPage. Vamos a indicar cual es la vista inicial de la aplicación, a continuación. Al añadir el paquete StarterPack en la PCL se añadió una clase llamada App que vamos a renombrar a MvxApp (puedes renombrarla a CoreApp, u otro nombre):

public class mvxApp : MvvmCross.Core.ViewModels.MvxApplication
{
     public override void Initialize()
     {
          CreatableTypes()
          .EndingWith("Service")
          .AsInterfaces()
          .RegisterAsLazySingleton();

          RegisterNavigationServiceAppStart<MvxMainViewModel>();
     }
}

Utilizamos el método RegisterNavigationServiceAppStart para indicar la viewmodel asociada a una vista que se mostrará como vista de inicio.

Todo listo a nivel de librería portable. Es hora de pasar a proyectos de cada plataforma.

Android

En cada plataforma vamos a contar con una clase llamada Setup encargada de hacer de bootstrapper ed MvvmCross (inicializa dependencias, componentes, etc). La mayoría de las acciones realizadas son virtuales, por lo que permiten personalización.

public class Setup : MvxFormsAndroidSetup
{
     public Setup(Context applicationContext) : base(applicationContext)
     {
     }

     protected override MvxFormsApplication CreateFormsApplication()
     {
          return new Core.App();
     }

     protected override IMvxApplication CreateApp()
     {
          return new Core.MvxApp();
     }

     protected override IMvxTrace CreateDebugTrace()
     {
          return new DebugTrace();
     }
}

Establecemos MvxFormsApplication y la implementación de IMvxApplication de nuestra PCL.

NOTA: Fíjate que el tipo base de la clase setup en Android es MvxFormsAndroidSetup. En la clase Setup añadida por StarterPack, el tipo es MvxAndroidSetup.

Por otro lado, modificamos la actividad principal para cambiar el tipo a MvxFormsAppCompatActivity:

public class MainActivity : MvxFormsAppCompatActivity
{
     protected override void OnCreate(Bundle bundle)
     {
          base.OnCreate(bundle);
          TabLayoutResource = Resource.Layout.Tabbar;
          ToolbarResource = Resource.Layout.Toolbar;
     }
}

iOS

Llegamos a iOS donde tendremos una serie de pasos a realizar, muy similares a Android. Comenzamos por la clase Setup:

public class Setup : MvxFormsIosSetup
{
     public Setup(IMvxApplicationDelegate applicationDelegate, UIWindow window)
     : base(applicationDelegate, window)
     {
     }

     protected override MvxFormsApplication CreateFormsApplication()
     {
          return new Core.App();
     }

     protected override IMvxApplication CreateApp()
     {
          return new Core.MvxApp();
     }

     protected override IMvxTrace CreateDebugTrace()
     {
          return new DebugTrace();
     }
}

También necesitamos modificar la clase AppDelegate:

[Register("AppDelegate")]
public partial class AppDelegate : MvxFormsApplicationDelegate
{
     public override UIWindow Window { get; set; }

     public override bool FinishedLaunching(UIApplication app, NSDictionary options)
     {
          Window = new UIWindow(UIScreen.MainScreen.Bounds);

          var setup = new Setup(this, Window);
          setup.Initialize();

          var startup = Mvx.Resolve<IMvxAppStart>();
          startup.Start();

          LoadApplication(setup.FormsApplication);

          Window.MakeKeyAndVisible();

          return true;
     }
}

Todo listo!

UWP

Al igual que en plataformas anteriores, comenzamos preparando la clase Setup:

public class Setup : MvxFormsWindowsSetup
{
     private readonly LaunchActivatedEventArgs launchActivatedEventArgs;

     public Setup(Windows.UI.Xaml.Controls.Frame rootFrame, LaunchActivatedEventArgs e) : base(rootFrame, e)
     {
          launchActivatedEventArgs = e;
     }

     protected override IMvxApplication CreateApp()
     {
          return new Core.MvxApp();
     }

     protected override IMvxWindowsViewPresenter CreateViewPresenter(IMvxWindowsFrame rootFrame)
     {
          Forms.Init(launchActivatedEventArgs);

          var presenter = new MvxFormsUwpViewPresenter(rootFrame, new MvxFormsApplication());
          Mvx.RegisterSingleton<IMvxViewPresenter>(presenter);

          return presenter;
     }

     protected override MvxLogProviderType GetDefaultLogProviderType() => MvxLogProviderType.None;
}

Modificamos la clase App.xaml.cs donde utilizaremos la clase Setup en el método OnLaunched tras inicializar Xamarin.Forms:

var setup = new Setup(rootFrame, e);
setup.Initialize();

Por último, en la página principal nativa del proyecto UWP:

public MainPage()
{
     InitializeComponent();

     var start = Mvx.Resolve<IMvxAppStart>();
     start.Start();

     var presenter = Mvx.Resolve<IMvxViewPresenter>() as MvxFormsUwpViewPresenter;

     LoadApplication(presenter.FormsApplication);
}

Llega la hora de trabajar con vistas y viewmodels

Las vistas, es decir, páginas en Xamarin.Forms deben extender de MvxContentPage. Por lo que debemos cambiar:

public partial class MvxMainView : ContentPage

Por:

public partial class MvxMainView : MvxContentPage<MvxMainViewModel>

De igual forma, en el XAML de la página, se debe utilizar el namespace:

xmlns:views="clr-namespace:MvvmCross.Forms.Core;assembly=MvvmCross.Forms"

Y definir la página como:

<views:MvxContentPage>

Por defecto, MvvmCross asociada vistas con ViewModels utilizando convención de nombres. Es decir, si tienes una vista llamada SignInView, la ViewModel debe llamarse SignInViewModel.

Cada ViewModel debe ser una clase que herede de MvxViewModel.

Ejemplo básico de uso de Mvx en Xamarin.Forms

Tienes un ejemplo de implementación básico disponible en GitHub:

Ver GitHub

Navegación

MvvmCross utiliza las ViewModels para realizar la navegación. Es decir, la navegación se realiza de ViewModel a Viewmodel en lugar de vista a vista. Tenemos disponible un servicio completo de navegación llamado IMvxNavigationService.

private readonly IMvxNavigationService _navigationService;

public FirstViewModel(IMvxNavigationService navigationService)
{
     _navigationService = navigationService;
}

Contamos con diferentes métodos para gestionar la navegación:

await _navigationService.Navigate<SecondViewModel, string>("parameter");

En el ejemplo anterior, navegamos a una vista llamada SecondView (asociada a la ViewModel llamada SecondViewModel) pasando un parámetro de tipo cadena.

También contamos con diferentes eventos que podemos utilizar en cada ViewModel para la gestión del ciclo de la navegación (navegar, recibir parámetros, etc.):

public override void Prepare(string parameter)
{
     Parameter = parameter;
}
Navegación

Tienes un ejemplo de implementación de navegación con MvvmCross disponible en GitHub:

Ver GitHub

NOTA: Para obtener más información acerca de la navegación en MvvmCross, consulta este enlace.

MvvmCross utiliza Presenter para navegar a vistas en cada plataforma nativa. Actúa como “pegamento” entre vistas y ViewModels. Como podemos deducir de su nombre, un Presenter toma una solicitud de presentación de una ViewModel y decide como presentar la UI. De esa forma, se logra una clara separación entre vistas y ViewModels. Esto también es clave para poder mostrar vistas nativas, Forms o una mezcla de ellas.

NOTA: Se puede cambiar tanto el comportamiento como del servicio de navegación como de Presenter.

Plugins

Haciendo una sencilla búsqueda de “plugin MvvmCross” en NuGet tendremos acceso a una gran variedad de paquetes. Tras añadir el paquete, podemos utilizar el plugin haciendo uso de inyección de dependencias o vía resolución de interfaz. Veamos un ejemplo haciendo uso de Acr.MvvmCross.Plugins.UserDialogs.

Mvx.RegisterSingleton<IUserDialogs>(() => UserDialogs.Instance);

A la hora de utilizar el plugin:

Mvx.Resolve<IUserDialogs>().Alert("Using Mvx Plugins!");
Uso de Plugins

Tienes un ejemplo de uso de plugins MvvmCross disponible en GitHub:

Ver GitHub

MvvmCross añade más funcionalidad en Xamarin.Forms como su propio sistema de enlace a datos (se puede utilizar perfectamente el de Xamarin.Forms) que añade opciones interesantes como Mutiple bindings o converters muy comunes por ejemplo. Sin embargo, en este artículo hemos visto los conceptos básicos necesarios en cualquier aplicación. En futuros artículos, continuaremos profundizando en otros conceptos así como ver otros frameworks y opciones!.

Más información