[Xamarin.Forms] Utilizando DependencyService

Razones para extender Xamarin.Forms

Xamarin.Forms es un toolkit que crea 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 DependencyService 02Application Markup Language (XAML).
Permite crear facilmente y con rapidez interfaces de usuario nativas
compartidas donde  cada elemento visual en Xamarin.Forms son mapeados a
elementos nativos y comportamientos propios de cada plataforma.

Sin embargo, esta posibilidad a veces supone grandes dudas, ¿podemos extender Xamarin.Forms en caso necesario?

Las necesidades principales para extender Xamarin.Forms son:

  • Modificar aspectos de la UI.
  • Aprovechar a fondo las capacidades que nos ofrece cada plataforma.
  • Cubrir ciertas necesidades creando nuevos controles o páginas.

Xamarin.Forms incluye un servicio de dependencia, DependencyService
que nos permite compartir interfaces de usuario y resolver con
facilidad la implementación de la misma en cada plataforma específica.
De esta forma podremos acceder a APIs específicas de cada plataforma
desde nuestra PCL o proyecto Shared.

En este artículo vamos a profundizar en el servicio de dependencia de Xamarin.Forms asi como su uso.

DependencyService

El servicio de dependencia nos permite acceder a funcionalidad nativa
de cada plataforma resolviendo la implementación de una sencilla
interfaz. El esquema general de uso del servicio de dependencia sería el
siguiente:

DependencyService

DependencyService

En el diagrama de la parte superior se detalla de forma visual los
pasos necesarios para poder realizar llamadas telefónicas desde la App.
Los pasos detallados serían:

  1. Creamos una interfaz común y compartida donde
    definimos la funcionalidad a cubrir en la implementación de cada
    plataforma. Esta interfaz estara definida dentro de nuestra PCL o
    proyecto Shared.
  2. En cada proyecto de cada plataforma, creamos la implementación de la interfaz.
  3. Utilizamos una etiqueta de registro en la implementación de la interfaz en cada plataforma para facilitar al servicio de dependencia la resolución.
  4. En nuestro código compartido (normalmente desde ViewModels) utilizaremos DependencyService.Get<> para obtener la implementación de la interfaz indicada específica de la plataforma en ejecución.

Utilizando DependencyService

Para analizar el uso del servicio de dependencia vamos a crear un nuevo proyecto desde cero:

Nueva App Xamarin.Forms

Nueva App Xamarin.Forms

Nuestro objetivo sera crear una App Xamarin.Forms destinada a iOS,
Android y Windows Phone que nos permita realizar llamadas por teléfono.

1. Creando la definición del Servicio

Comenzamos creando una carpeta Services en nuestro proyecto PCL. Dentro de esta carpeta creamos una interfaz:

public interface ICallService
{
     void MakeCall(string phone);
}

La interfaz nos definirá la implementación que será necesaria en cada
plataforma. En nuestro caso, un sencillo método al que le pasamos el
número de teléfono y nos permite realizar la llamada (MakeCall).

2. Implementando la interfaz en cada plataforma

El siguiente paso consistirá en realizar la implementación de la interfaz en cada proyecto nativo.

La implementación en Windows Phone:

class CallService : ICallService
{
     public static void Init() { }
 
     public void MakeCall(string phone)
     {
          var phoneCallTask = new PhoneCallTask { PhoneNumber = phone };
 
          phoneCallTask.Show();
     }
}

NOTA: Las clases con implementación requieren de un contructor sin parámetros para que el servicio de dependencia pueda resolverla.

La implementación en Android:

public class CallService : ICallService
{
     public static void Init()
     {
 
     }
 
     public void MakeCall(string phone)
     {
         if (System.Text.RegularExpressions.Regex.IsMatch(phone, "^(\(?\+?[0-9]*\)?)?[0-9_\- \(\)]*$"))
         {
             var uri = Android.Net.Uri.Parse(String.Format("tel:{0}", phone));
             var intent = new Intent(Intent.ActionView, uri);
             Xamarin.Forms.Forms.Context.StartActivity(intent);
         }
         else
         {
             Debug.WriteLine("Invalid number!");
         }
     }
}

En iOS:

public class CallService : ICallService
{
     public static void Init() { }
 
     public void MakeCall(string phone)
     {
         if (System.Text.RegularExpressions.Regex.IsMatch(phone, "^(\(?\+?[0-9]*\)?)?[0-9_\- \(\)]*$"))
         {
             var url = new NSUrl(string.Format(@"telprompt://{0}", phone));
             UIApplication.SharedApplication.OpenUrl(url);
         }
         else
         {
             Debug.WriteLine("Invalid phone number!");
         }
     }
}

3. Registro de la implementación

Añadimos la etiqueta [assembly] encima de la clase, incluido la definición del namespace.

[assembly: Dependency(typeof(CallService))]

Este atributo registra la clase como implementación de la interfaz
ICallService. Esto permitirá acceder a la instancia de la implementación
desde código compartido utilizando DependencyService.Get<ICallService>().

4. Utilizar el servicio desde la PCL o proyecto Shared

Llegados a este punto lo tenemos todo listo, solo nos falta utilizar el servicio!.

ICallService callService = DependencyService.Get<ICallService>();
callService.MakeCall(“6123456789”);

Ejecutando la App:

Nuestra App!

Nuestra App!

Añadiendo el número de teléfono y pulsando sobre el botón:

Llamar por teléfono

Llamar por teléfono

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

También tenéis el código fuente disponible e GitHub:

Ver GitHub

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

Más información

[Evento WPSUG] Mobile retention: consigue fidelizar a los usuarios de tu app

Introducción

¿Sabes que sólo un 40% de los usuarios abre por segunda vez una app que
tiene instalada en el móvil? ¿Qué debemos hacer para que esto no nos
pase a nosotros? Crear valor, fidelizar y una buena comunicación son
claves para que nuestra App utilice continuamente.

El evento

El próximo Miércoles 01 de Julio, a las 19:00 (GMT+1)  tendra lugar un Hangout en el que tendremos el placer de contar con Vanessa Estorach, con quien veremos cómo varía la retención en función de la temática de las apps y verás cómo conseguir que tus usuarios sean fieles y vuelvan a utilizarla.

  • 19:00 en España
  • 13:00 en Colombia
  • 12:00 en México Centro
  • 13:30 en Venezuela
  • 15:00 en Chile continental

¿Te apuntas?

Más información

[Xamarin.Forms] Custom Renders

Introducción

Xamarin.Forms es un toolkit que crea 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).
Permite crear facilmente y con rapidez interfaces de usuario nativas
compartidas donde  cada elemento visual en Xamarin.Forms son mapeados a
elementos nativos y comportamientos propios de cada plataforma.

Sin embargo, esta posibilidad a veces supone grandes dudas, ¿podemos crear o modificar elementos visuales de Xamarin.Forms?

Xamarin.Forms utiliza abstracciones
para definir los elementos. Posteriormente se transforma cada
abstracción ofreciendo una implementación y mecanismos en cada
plataforma.

¿Qué podemos hacer?
¿Qué podemos hacer?

En
este artículo vamos a ver que podemos crear nuestras propias
abstracciones ya sea modificando alguna de las existentes o partiendo
desde prácticamente cero.

¿Cuándo son necesarios?

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. Con la llegade de la
versión 1.3 de Xamarin.Forms llegaron los estilos. Los estilos permitir definir múltiples propiedades visuales de elementos de la interfaz de forma reutilizable.

Por lo tanto, para modificaciones visuales simples no es necesario realizar ningun tipo de Custom Render.

¿Cúando serán necesario?

¿Cuándo crear Custom Renders?
¿Cuándo crear Custom Renders?

Tenemos varias opciones:

  • Modificar la apariencia de elementos a niveles no posibles por estilos.
  • Modificar el comportamiento de elementos existentes.
  • Crear nuevos controles personales.

Extender
Xamarin.Forms nos permitirá añadir funcionalidad, controles y páginas
específicas para cada plataforma logrando que nuestras Apps se adapten a
la perfección a las guías de estilo de cada plataforma.

Custom Renders

Los
elementos de Xamarin.Forms, páginas, layouts y controles, utilizan una
API común que permite crear interfaces visuales con el mismo código para
todas las plataformas. Cada página, layout o control se renderiza de
forma diferente en cada plataforma.  El esquema de que ocurre es el
siguiente:

Element y Renderer
Element y Renderer

Todos los elementos de Xamarin.Forms se componen de dos partes diferenciadas, Element y Renderer.

  • Element:
    Es una clase que define al control. Conjunto de propiedades y eventos
    que permitirán gestionar tanto la apariencia, contenido y comportamiento
    del mismo. En el esquema superior nos centramos en el elemento Button. La clase Element define el conjunto de propiedades de contenido (Text), como las de apariencia (TextColor) y eventos.
  • Renderer:
    El elemento definido se renderiza (transforma) en cada plataforma a un
    elemento 100% nativo. En el esquema anterior, la clase Renderer en cada
    plataforma creará un control nativo, UIButton en iOS y Button en Android y Windows Phone, asignando las definiciones que vienen establecidas desde el Element.

Podemos crear nuestra propia clase Renderer para modificar la apariencia o comportamiento del elemento.

Custom Render
Custom Render

Podemos añadir un render personalizado por plataforma o sobreescribir el comportamiento en cada una de las plataformas.

Creando Custom Renders

Comenzamos creando la clase Element de definición de nuestro control. En este caso vamos a crear un control tipo hipervínculo.

public class HyperLinkControl : Label
{
     public static readonly BindableProperty NavigateUriProperty;
 
     static HyperLinkControl()
     {
         NavigateUriProperty = BindableProperty.Create("NavigateUri", typeof (string), typeof (HyperLinkControl),
             string.Empty);
     }
 
     public string NavigateUri
     {
         get { return (string) base.GetValue(NavigateUriProperty); }
         set { base.SetValue(NavigateUriProperty, value); }
     }
}

En nuestra PCL dentro de la carpeta CustomControls creamos
una nueva clase. Esta clase heredará de algun otro elemento que contenga
ya el comportamiento o aspecto visual similar al objetivo buscado. En
nuestro caso, al querer crear un enlace que contendrá texto visible que
podremos personalizar, heredamos del control Label.

NOTA: Si es control es totalmente nuevo sin similitudes con elementos existentes, la herencia será del elemento View.

La
clase nos permitirá definir nuestro control. Deseamos contar con las
mismas propiedades que el Label, de ahi la herencia pero además
necesitamos poder especificar el enlace al que se navegará pulsando
sobre el mismo.

El enlace lo especificamos creando una nueva BindableProperty.
Esta clase nos permite crear propiedades que describen a la misma, tipo
y contenido, además de especificar como lanzar el cambio de la
propiedad. Nuestra propiedad NavigateUri es de tipo string.

Llegados a este punto, tenemos definida nuestra clase Element. Ahora es el turno de crear en cada proyecto de cada plataforma la clase Renderer correspondiente.

En el proyecto Windows Phone, dentro de la carpeta Controls:

public class HyperLinkControlRenderer : ViewRenderer<HyperLinkControl, HyperlinkButton>
{
     protected override void OnElementChanged(ElementChangedEventArgs<HyperLinkControl> e)
     {
         base.OnElementChanged(e);
 
         if (e.OldElement != null || Element == null)
             return;
 
         var element = new HyperlinkButton
         {
             TargetName = Element.Text,
             Content = Element.Text
         };
 
         element.Click += (sender, args) =>
         {
             if (Element.NavigateUri.Contains("@"))
             {
                 var emailComposeTask = new EmailComposeTask { Subject = string.Empty, To = "mailto:" + Element.NavigateUri };
                 emailComposeTask.Show();
             }
             else if (Element.NavigateUri.Contains("www.") ||
                 Element.NavigateUri.Contains("http:"))
             {
                 var uri = Element.NavigateUri.StartsWith("http:")
                               ? new Uri(Element.NavigateUri)
                               : new Uri(@"http://" + Element.NavigateUri);
 
                 var webBrowserTask = new WebBrowserTask { Uri = uri };
                 webBrowserTask.Show();
             }
         };
 
         SetNativeControl(element);
     }
 
     protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
     {
         base.OnElementPropertyChanged(sender, e);
 
         if ((e.PropertyName == Label.TextProperty.PropertyName))
             Control.Content = Element.Text;
     }
}

La clase hereada de ViewRenderer lo que significa
que crearemos una vista personalizada, Xamarin.Forms se encargará de la
gestión de cálculos de tamaño y propiedades comunes de una vista. Le
indicamos que clase estamos renderizando (clase Element), en nuestro ejemplo HyperLinkControl, y que elemento nativo se renderizará. En Windows Phone, el control HyperLinkControl renderizará un control de tipo HyperLinkButton.

Una vez especificada la clase y su herencia, lo único que tenemos que
hacer es crear nuestro control nativo, establecerle las propiedades
correspondientes y renderizarlo. Hacemos esto utilizando el método OnElementChanged. En este método:

  • Tenemos acceso a la propiedad Element que es nuestro HyperLinkControl creado previamente con las propiedades que definimos.
  • Tenemos acceso al control pudiéndole establecer lo que necesitemos utilizando el método SetNativeControl.

NOTA: Al especificar en la herencia del renderer
el tipo del Element y del control nativo a renderizar, Element y
Control cuentan ya con los tipos correctos establecidos lo que nos
facilita la tarea sin necesidades de realizar castings.

En Windows Phone al pulsar el elemento utilizamos el evento Click del control nativo y verificamos si es una URL o un correo. Si es URL utilizamos WebBrowserTask para abrirla y en el caso de ser correo, utilizamos EmailComposeTask. Como vemos, son APIs específicas y nativas de Windows Phone.

Para indicar la clase que renderizará en la plataforma a la clase Element definida, lo haremos utilizando el atributo [assembly] en la parte superior de la clase, incluido la definición del namespace.

[assembly: ExportRenderer(typeof(HyperLinkControl), typeof(HyperLinkControlRenderer))]

Utilizando ExportRenderer le indicamos a Xamarin.Forms que en el proyecto Windows Phone se establece el renderizado de nuestro control HyperLinControl.

Ahora llega el turno de Android:

public class HyperLinkControlRenderer : LabelRenderer
{
     protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
     {
         base.OnElementChanged(e);
 
         if (e.OldElement == null)
         {
             var nativeEditText = Control;
 
             Linkify.AddLinks(nativeEditText, MatchOptions.All);
         }
     }
}

En este caso, la clase hereda del renderer específico del Label, LabelRenderer. Volvemos a utilizar el método OnElementChanged para acceder y establecer las propiedades. En este caso, utilizamos Linkify que tomará un texto y una expresión regular para crear enlaces.

Y por último iOS:

public class HyperLinkControlRenderer : LabelRenderer
{
     protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
     {
         base.OnElementChanged(e);
 
         if (e.OldElement == null)
         {
             var label = Control;
             label.TextColor = UIColor.Red;
             label.BackgroundColor = UIColor.Clear;
             label.UserInteractionEnabled = true;
             var tap = new UITapGestureRecognizer();
 
             tap.AddTarget(() =>
             {
                 var hyperLinkLabel = Element as HyperLinkControl;
 
                 if (hyperLinkLabel != null)
                 {
                     var uri = hyperLinkLabel.NavigateUri;
 
                     if (uri.Contains("@") && !uri.StartsWith("mailto:"))
                         uri = string.Format("{0}{1}", "mailto:", uri);
                     else if (uri.StartsWith("www."))
                         uri = string.Format("{0}{1}", @"http://", uri);
 
                     UIApplication.SharedApplication.OpenUrl(new NSUrl(uri));
                 }
             });
 
             tap.NumberOfTapsRequired = 1;
             tap.DelaysTouchesBegan = true;
             label.AddGestureRecognizer(tap);
         }
     }
}

Al igual que en Android, heredamos de LabelRenderer.
En el método OnElementChanged accedemos a las propiedades, verificamos
el tipo de enlace, le añadimos el schema adecuado segun el tipo, y se
utiliza UIApplication.SharedApplication.OpenUrl para abrir el enlace.

Todo listo!. Bueno… casi, nos falta utilizar el control. Desde
nuestra PCL en una vista definiremos el namespace donde tenemos
declarado nuestro control:

xmlns:custom="clr-namespace:CustomRenders.CustomControls;assembly=CustomRenders"

Ahora podemos definir el nuevo control (tanto desde XAML como desde C#)
utilizando nuestra porpiedad NavigateUri para indicar enlaces a páginas
webs o correos electrónicos:

<StackLayout Padding="20" Spacing="20">
   <Label Text="HyperLinkControl" />
   <custom:HyperLinkControl Text="Email"
                            NavigateUri="user@mail.com" />
   <custom:HyperLinkControl Text="Url"
                            NavigateUri="https://javiersuarezruiz.wordpress.com" />
</StackLayout>

El resultado:

El resultado

El resultado

Pulsando en el segundo enlace:

Funciona!

Funciona!

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

También tenéis el código fuente disponible e GitHub:

Ver GitHub

¿Puedo utilizar controles nativos de cada plataforma?

Utilizamos un mundo de abstracciones que nos permiten definir vistas
para cada plataforma con un código común. Ya hemos visto como poder
modificar el aspecto o el comportamiento de elementos existentes además
de crear nuevos pero… ¿podemos utilizar controles nativos existentes para alguna plataforma concreta?

La respuesta es sencilla y posiblemente ya sido deducida, si. Utilizaremos Custom Renders para ello.

Vamos a crear un nuevo ejemplo donde crearemos un nuevo control para Xamarin.Forms que en Windows Phone renderizará un Tile dinámico. En el proyecto, dentro de la carpeta CustomControls, creamos una nueva clase:

public class CustomHubTileView : View
{
     public static readonly BindableProperty TitleProperty = BindableProperty.Create<CustomHubTileView, string>(p => p.Title, string.Empty);
 
     public string Title
     {
         get { return (string)GetValue(TitleProperty); }
         set { SetValue(TitleProperty, value); }
     }
 
     public static readonly BindableProperty MessageProperty = BindableProperty.Create<CustomHubTileView, string>(p => p.Message, string.Empty);
 
     public string Message
     {
         get { return (string)GetValue(MessageProperty); }
         set { SetValue(MessageProperty, value); }
     }
 
     public static readonly BindableProperty SourceProperty = BindableProperty.Create<CustomHubTileView, ImageSource>(p => p.Source, string.Empty);
 
     public ImageSource Source
     {
         get { return (ImageSource)GetValue(SourceProperty); }
         set { SetValue(SourceProperty, value); }
     }
 
     public static readonly BindableProperty ColorProperty = BindableProperty.Create<CustomHubTileView, Color>(p => p.Color, Color.Default);
 
     public Color Color
     {
         get { return (Color)GetValue(ColorProperty); }
         set { SetValue(ColorProperty, value); }
     }
}

Será un control nuevo, heredamos de View. Dentro de la clase creamos múltiples BindableProperty:

  • Title: Propiedad de tipo string que mostrará el texto mostrado en la vista principal del Tile.
  • Message: Propiedad ed tipo string que mostrará el texto secundario del Tile.
  • Source: Imagen del Tile.
  • Color: Color de fondo del Tile.

Tras crear el Element con la definición del control, en el proyecto de la plataforma, Windows Phone, crearemos el Renderer:

public class CustomHubTileViewRenderer : ViewRenderer<CustomHubTileView, HubTile>
{
     private HubTile HubTile;
 
     public CustomHubTileViewRenderer()
     {
         HubTile = new HubTile
         {
             Margin = new System.Windows.Thickness(5)
         };
     }
 
     protected override void OnElementChanged(ElementChangedEventArgs<CustomHubTileView> e)
     {
         base.OnElementChanged(e);
 
         if (e.OldElement != null || Element == null)
             return;
 
         HubTile.Title = Element.Title;
         HubTile.Message = Element.Message;
         var fileImageSource = Element.Source as FileImageSource;
         if(fileImageSource != null)
             HubTile.Source = new BitmapImage(new Uri(fileImageSource.File, UriKind.RelativeOrAbsolute));
 
         System.Windows.Media.Color color = System.Windows.Media.Color.FromArgb(
                (byte)(Element.Color.A * 255),
                (byte)(Element.Color.R * 255),
                (byte)(Element.Color.G * 255),
                (byte)(Element.Color.B * 255));
 
         HubTile.Background = new SolidColorBrush(color);
 
         SetNativeControl(HubTile);
     }
 
     protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
     {
         base.OnElementPropertyChanged(sender, e);
 
         if (Control == null || Element == null)
             return;
 
         if (e.PropertyName == CustomHubTileView.TitleProperty.PropertyName)
             HubTile.Title = Element.Title;
 
         if (e.PropertyName == CustomHubTileView.MessageProperty.PropertyName)
             HubTile.Message = Element.Message;
     }
}

En el proyecto Windows Phone 8.0, utilizaremos el control nativo HubTile incluido dentro del paquete Windows Phone Toolkit. Utilizamos el método OnElementChanged para establecer todas las propiedades asignadas y renderizar el control.

Para indicar la clase que renderizará en la plataforma a la clase Element definida, lo haremos utilizando el atributo [assembly] en la parte superior de la clase, incluido la definición del namespace.

[assembly: ExportRenderer((typeof(CustomHubTileView)), typeof(CustomHubTileViewRenderer))]

A la hora de utilizarlo, definimos el namespace donde tenemos al control declarado:

xmlns:custom="clr-namespace:HubTileXamarinForms.CustomControls;assembly=HubTileXamarinForms"

Desde una vista:

<custom:CustomHubTileView
        Title="Arroces"
        Message="25 recetas"
        Source="../Assets/arroces.jpg"
        Color="Red" />

El resultado:

El resultado

El resultado

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

También tenéis el código fuente disponible e GitHub:

Ver GitHub

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

Más información

[Tips and Tricks] Como añadir App.xaml en Xamarin.Forms

XAMLIntroducción

Xamarin.Forms es un toolkit que crea 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).

Cuando creamos una nueva Aplicación Xamarin.Forms:

AppXAML 01

Automáticamente se nos crea una estructura con cuatro proyectos, tres
por cada plataforma nativa y uno con el código común que segun elección
será una PCL o un proyecto Shared. En el código compartido se nos
creará un archivo llamado App.cs:

Estructura de proyecto Xamarin.Forms

Este archivo es el punto de entrada de la App donde se establece la
vista inicial, se realizan inicializaciones y se gestiona el ciclo de
vida compartido de la App. Los desarrolladores .NET con experiencia en
WPF, Windows Phone o Windows Store están acostumbrados a utilizar
también un fichero XAML asociado donde se pueden establecer estilos
comunes a toda la Aplicación además de incluir estilos definidos en
diccionario de recursos. Una forma sencilla y bastante potente para
poder organizar todos los recursos y estilos necesarios.

¿Podemos haer algo similar con Xamarin.Forms?

En este artículo vamos a aprender como reemplazar el archivo App.cs por un archivo App.xaml con su App.xaml.cs asociado.

Creando el archivo App.xaml

En nuestra PCL o proyecto Shared vamos a incluir un nuevo fichero de tipo Forms Xaml Page:

Añadimos App.xaml

Al añadir este archivo veremos la siguiente vista XAML:

<?xml version="1.0" encoding="utf-8" ?>
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MyXamarinFormsApp.App">
  <Label Text="{Binding MainText}" VerticalOptions="Center" HorizontalOptions="Center" />
</ContentPage>

Con el siguiente código asociado:

public partial class App : ContentPage
{
     public App()
     {
         InitializeComponent();
     }
}

Suprimimos el archivo App.cs y realizamos la siguiente modificación en App.xaml.cs:

<?xml version="1.0" encoding="utf-8" ?>
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MyXamarinFormsApp.App">
 
</Application>

Reemplazamos ContentPage por Application. En el código asociado, la clase derivará también de Application
y de manera opcional añadiremos la sobreescritura de los métodos que
necesitemos (como por ejemplo, los eventos del ciclo de vida).

public partial class App : Application
{
     public App()
     {
 
     }
 
     protected override void OnStart()
     {
         // Handle when your app starts
     }
 
     protected override void OnSleep()
     {
         // Handle when your app sleeps
     }
 
     protected override void OnResume()
     {
         // Handle when your app resumes
     }
}

Si ejecutamos en este punto, todo funcionará exactamente igual a antes del cambio.

Estilos a nivel de Aplicación

Podemos definir recursos a nivel de Aplicación donde crear desde
recursos a estilos más complejos a compartir a lo largo de toda la
aplicación:

<Application.Resources>  
     <ResourceDictionary>
          <Style
               x:Key="AppButtonStyle"
               TargetType="Button">
               <Setter Property="Rotation" Value="25" />
          </Style>
     </ResourceDictionary>
</Application.Resources>

En nuestra vista principal podemos acceder al estilo definido en App.xaml:

<Style x:Key="InheritedAppButtonStyle" TargetType="Button" BasedOn="{StaticResource AppButtonStyle}">
     <Setter Property="BorderColor" Value="Green" />
     <Setter Property="FontSize" Value="Large" />
</Style>

El botón en nuestra vista principal:

<Button
     Text="Herencia de Estilos desde App"
     Style="{StaticResource InheritedAppButtonStyle}"/>

El resultado:

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

También podéis acceder al código fuente directamente en GitHub:

Ver GitHub

Más información

[Material] Mobile Dev Day

El Evento

El pasado Lunes 15 de Junio tenía lugar el evento Mobile Dev Day en las oficinas de Microsoft Ibérica
Un evento con múltiples charlas relacionadas con el desarrollo de Apps
para Windows 10, Apps móviles multiplataforma con Xamarin y detalles
relacionados con el desarrollo de las mismas como la gestión de equipos y
tareas, Builds y Testing.

El Material

Windows 10 ha llegado como la culminación en el viaje hacia la convergencia en el desarrollo entre plataformas Windows. Ahora hablamos de Apps Universales
escritas una única vez con un código común tanto para la lógica de
negocio como para la interfaz de usuario. Además, generamos un único
paquete que mantendrá una interfaz consistente y familiar para el
usuario pero adaptada a cada plataforma. Podemos crear apps que
funcionen en todo tipo de dispositivos como teléfonos, tabletas,
portátiles, dispositivos IoT, Surface Hub e incluso HoloLens.

Comenzamos el evento con
una sesión donde tratamos todas las novedades principales sobre
desarrollo Windows 10: SDK de extensiones, diseño adaptativo, SplitView,
vistas por familias de dispositivos, novedades en XAML, en controles o
en herramientas por ejemplo.

Nuestro
objetivo como desarrolladores es crear aplicaciones útil y atractivas
pero sobretodo perfectamente funcionales. Para poder lograr ese objetivo
es sin duda muy importante la arquitectura aplicada a la App. En la
siguiente sesión vimos el patrón MVVM aplicándolo a una
aplicación Xamarin en cada una de las plataformas paso a paso así como
la cantidad de código que se puede llegar a compartir entre ellas.

Para finalizar el evento, nos centramos en Visual Studio Online
Repasamos conceptos claves en la gestión del ciclo de vida completo de
nuestro proyecto con metodologías ágiles, así como gestionar nuestro
código fuente para terminar viendo como automatizar la compilación o las
pruebas  en nuestros proyectos móviles incluidos desde recientemente
proyectos Xamarin.

En cuanto a las Demos técnicas y Apps realizadas, la tenéis disponibles en GitHub:

Ver GitHub

Quisiera terminar agradeciendo a Microsoft y Bravent por permitir estas actividades y por supuesto a todos los asistentes. Espero que para todos fuese una mañana divertida!

Más información

[Material] Seminario Xamarin en Avante

El Evento

El pasado Martes 09 de Junio tenía lugar Apps Multiplataforma con Xamarin en el Avante.  Un evento con múltiples charlas relacionadas con el desarrollo de Apps móviles multiplataforma con Xamarin.

El Material

Comenzamos el evento con una sesión donde
repasamos el estado actual del mercado y el desarrollo móvil,
introducción a Xamarin como herramienta para crear aplicaciones nativas
multiplataforma desde Visual Studio analizando todas sus bondades y
costes además de ver distintas opciones, Xamarin Classic y
Xamarin.Forms.

Nuestro objetivo como desarrolladores es crear
aplicaciones útil y atractivas pero sobretodo perfectamente
funcionales. Para poder lograr ese objetivo es sin duda muy importante
la arquitectura aplicada a la App. En la siguiente sesión repasaremos el
patrón MVVM aplicándolo a una aplicación Xamarin en cada una de las
plataformas paso a paso así como la cantidad de código que se puede
llegar a compartir entre plataformas.

El ecosistema Xamarin no cesa en las
herramientas de desarrollo. Tenemos a disposición una gran variedad de
servicios destinados a complementar el mismo, analíticas, testing,
análisis de rendimiento, etc. En esta sesión hicimos un repaso por todos
los servicios disponibles realizando demos de cada uno de ellos.

 

En cuanto a las Demos técnicas y Apps realizadas, la tenéis disponibles en GitHub:

Ver GitHub

Quisiera terminar agradeciendo a Avante y Bravent por permitir estas actividades y por supuesto a todos los asistentes. Espero que para todos fuese una mañana divertida y… ¿cuándo repetimos?

Más información

Avante: Seminario Xamarin

[Evento] Mobile Dev Day

El evento

El próximo Lunes 15 de Junio, Microsoft y Bravent han
organizado un evento donde veremos una gran cantidad de aspectos
relacionadas con el desarrollo móvil. Trataremos aspectos como las
novedades a nivel de desarrollo que tenemos con la llegada de Windows
10, como crear y estructurar proyectos móviles multiplataforma
utilizando Xamarin llegando a compartir la mayor cantidad de código
posible tanto con MVVMCross como con Xamarin.Forms además de ver como
gestionar el ciclo de vida de proyectos con metodologías ágiles
automatizando Builds y tests incluidos proyectos móviles
multiplataforma.

¿Te apuntas?

Agenda

  • 10:00h – 10:30h Registro
  • 10:35h – 11:35h Windows 10: Universal Windows Platform.
    Windows 10 ha llegado como la culminación en el viaje hacia la
    convergencia en el desarrollo entre plataformas Windows. Ahora hablamos
    de Apps Universales escritas una única vez con un código común tanto
    para la lógica de negocio como para la interfaz de usuario. Además,
    generamos un único paquete que mantendrá una interfaz consistente y
    familiar para el usuario pero adaptada a cada plataforma. Podemos crear
    apps que funcionen en todo tipo de dispositivos como teléfonos,
    tabletas, portátiles, dispositivos IoT, Surface Hub e incluso HoloLens.
    En esta sesión conoceremos todas las novedades sobre desarrollo Windows
    10.
  • 11:35h – 12:05h Desayuno
  • 12:05h – 13:05h Crear Apps Multiplataforma nativas reutilizando la mayor cantidad de código.
    Aprende a sacar todo el provecho a Xamarin y reutilizar la mayor parte
    del código entre diferentes plataformas, disminuyendo los tiempos de
    desarrollo y facilitando el mantenimiento.
  • 13:05h – 14:05h Novedades en Visual Studio Online.
    Veremos cómo con Visual Studio Online podemos gestionar el ciclo de
    vida completo de nuestro proyecto con metodologías ágiles, así como
    gestionar nuestro código fuente y automatizar la compilación o las
    pruebas incluidas desde recientemente Apps Xamarin.

Fecha

El evento tendrá lugar el próximo Lunes, 15 de Junio de 10:00h a 14:00h. Tendremos tres sesiones de 1 horas de duración cada una.

Lugar

Tendrá lugar en el Microsoft Ibérica situado en el Centro Empresarial La Finca. Tenéis la información exacta del lugar a continuación:

Microsoft Ibérica S.R.L.
Paseo Club Deportivo
Centro Empresarial La Finca – Edificio 1 Pozuelo de Alarcón España

Más información

[Windows 10] La nueva Title Bar

Introducción

Las aplicaciones Windows 10 corren como cualquier otra aplicación de
escritorio en formato ventana. Esta característica añade un nuevo
componente llamado TitleBar que contiene el título de
la Aplicación a la izquierda con los tres conocidos botones para
minimizar, expandir y cerrar a la derecha.

¿Qué opciones presenta?, ¿hasta dónde podemos personalizarlo?

En este artículo vamos a utilizar y personalizar las opciones disponibles de la TitleBar de diferentes formas.

La nueva Title Bar

Crearemos un nuevo proyecto UAP:

Añadimos las carpetas Views, ViewModels y Services además de las clases base necesarias para implementar el patrón MVVM de la misma forma que vimos en este artículo.

Nuestro objetivo será trabajar y modificar todas las opciones disponibles en la TitleBar. Veremos a continuación que para trabajar con ella accederemos utilizando ApplicationView.GetForCurrentView().TitleBar por lo que primero aprenderemos como trabajar con ella de forma simple desde code behind para posteriormente crearnos un Behavior y poder modificar sus propiedades directamente desde XAML.

Comenzamos creando nuestra interfaz:

<StackPanel
     HorizontalAlignment="Center"
     VerticalAlignment="Center">
     <Button Content="Use Code Behind"
             Click="CodeBehindClick"
             Margin="5"/>
     <Button Content="Use Behavior"
             Command="{Binding NavigateCommand}"
             Margin="5"/>
</StackPanel>

Muy simple. Contamos con dos botones. El primero de ellos modificará la apariencia de la TitleBar desde un evento en el code behind mientras que el segundo navegará a una nueva vista donde se modificará la apariencia de la TitleBar desde XAML utilizando un Behavior.

NOTA: La TitleBar muestra por defecto un color de fondo gris y los elementos con color negro.

El evento del primer botón:

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

Tendremos en la ViewModel el comando correspondiente al segundo botón:

private ICommand _navigateCommand;
       
public ICommand NavigateCommand
{
     get { return _navigateCommand = _navigateCommand ?? new DelegateCommand(NavigateCommandExecute); }
}
 
private void NavigateCommandExecute()
{
            
}  

Nos centramos en el evento del primer botón. Podemos modificar el texto
que aparece como título en la TitleBar de forma sencilla:

var applicationView = ApplicationView.GetForCurrentView();
 
// Title

applicationView.Title = "Changed basic TitleBar Information"

Utilizando el método GetForCurrentView de la clase ApplicationView obtenemos la instancia de la ventana correspondiente a la App. Esta instancia cuenta con una nueva propiedad llamada TitleBar que nos da acceso a la misma. Tenemos acceso a las siguientes propiedades básicas para modificar el aspecto:

  • BackgroundColor: Propiedad de tipo Color que define el color de fondo de la barra de título sin incluir el fondo de los botones.
  • ForegroundColor: Propiedad de tipo Color utilizada en el color del texto de título.
  • ButtonBackgroundColor: Propiedad de tipo Color para el fondo de la zona de botones en la parte derecha.
  • ButtonForegroundColor: Propiedad de tipo Color que define el color de los botones.
// Basic TitleBar Properties
var titleBar = applicationView.TitleBar;
titleBar.BackgroundColor = (Color)App.Current.Resources["RedColor"];
titleBar.ForegroundColor = (Color)App.Current.Resources["WhiteColor"];
titleBar.ButtonBackgroundColor = (Color)App.Current.Resources["BlueColor"];

titleBar.ButtonForegroundColor = (Color)App.Current.Resources["WhiteColor"];

Más alla de las propiedades de personalización básica que hemos utilizado, podemos modificar muchas otras como:

// Extra
titleBar.ButtonHoverBackgroundColor = Colors.Yellow;
titleBar.ButtonPressedBackgroundColor = Colors.Orange;

Donde:

  • ButtonHoverBackgroundColor: Propiedad de tipo Color que define el color de fondo del botón al pasar el ratón por encima.
  • ButtonPressedBackgroundColor: Propiedad de tipo Color  para el fondo del botón al ser pulsado.

Tenemos gran cantidad de propiedades para definir la apariencia visual en múltiples estados. Si ejecutamos la App:

Al pasar el ratón sobre cualquier botón de la TitleBar:

Pulsando sobre un botón:

Sencillo, ¿cierto?

Mejorando lo presente, utilizando Behavior

Como hemos podido ver hasta ahora:

  • La TitleBar define la cabecera de nuestra App incluyendo título y botones de gestión (minimizar, maximizar y cerrar).
  • Podemos personalizar el contenido del título.
  • Podemos personalizar totalmente la apariencia.

Sin embargo, en lo visto hasta ahora hacemos uso de code behind.

¿Cómo podemos personalizar la TitleBar directamente desde XAML?

Crearemos un Behavior para ello. Añadiremos la referencia a Extensions SDK:

En nuestro proyecto, dentro de la carpeta Behaviors, crearemos una nueva clase que heredará de IBehavior:

public class TitleBarBehavior : DependencyObject, IBehavior
{
     public DependencyObject AssociatedObject { get; private set; }
 
     public void Attach(DependencyObject associatedObject)
     {
         var titleBar = associatedObject as UIElement;
         if (titleBar == null)
             throw new ArgumentException(
                 "TitleBarBehavior can be attached only to UIElement!");
 
         Window.Current.SetTitleBar(titleBar);
 
         AssociatedObject = associatedObject;
     }
 
     public void Detach()
     {
         AssociatedObject = null;
     }
}

Realizamos la implementación de la interfaz IBehavior asociando el Behavior a un elemento UIElement. A continuación, crearemos propiedades de dependencia para modificar el contenido y aspecto de la TitleBar.

public Color BackgroundColor
{
     get { return (Color)GetValue(BackgroundColorProperty); }
     set { SetValue(BackgroundColorProperty, value); }
}
 
public static readonly DependencyProperty BackgroundColorProperty =
            DependencyProperty.Register("BackgroundColor",
            typeof(Color),
            typeof(TitleBarBehavior),
            new PropertyMetadata(false, OnBackgroundColorChanged));
 
private static void OnBackgroundColorChanged(DependencyObject d,
            DependencyPropertyChangedEventArgs e)
{
     var applicationView = ApplicationView.GetForCurrentView();
     applicationView.TitleBar.BackgroundColor = (Color)e.NewValue;
}
 
public string Title
{
     get { return (string)GetValue(TitleProperty); }
     set { SetValue(TitleProperty, value); }
}
 
public static readonly DependencyProperty TitleProperty =
            DependencyProperty.Register("Title",
            typeof(string),
            typeof(TitleBarBehavior),
            new PropertyMetadata(string.Empty, OnTitleChanged));
 
private static void OnTitleChanged(DependencyObject d,
            DependencyPropertyChangedEventArgs e)
{
     var applicationView = ApplicationView.GetForCurrentView();
     applicationView.Title = (string)e.NewValue;
}
 
public Color ForegroundColor
{
     get { return (Color)GetValue(ForegroundColorProperty); }
     set { SetValue(ForegroundColorProperty, value); }
}
 
public static readonly DependencyProperty ForegroundColorProperty =
            DependencyProperty.Register("ForegroundColor",
            typeof(Color),
            typeof(TitleBarBehavior),
            new PropertyMetadata(false, OnForegroundColorChanged));
 
private static void OnForegroundColorChanged(DependencyObject d,
            DependencyPropertyChangedEventArgs e)
{
     var applicationView = ApplicationView.GetForCurrentView();
     applicationView.TitleBar.ForegroundColor = (Color)e.NewValue;
}
 
public Color ButtonForegroundColor
{
     get { return (Color)GetValue(ButtonForegroundColorProperty); }
     set { SetValue(ButtonForegroundColorProperty, value); }
}
 
public static readonly DependencyProperty ButtonForegroundColorProperty =
            DependencyProperty.Register("ButtonForegroundColor",
            typeof(Color),
            typeof(TitleBarBehavior),
            new PropertyMetadata(false, OnButtonForegroundColorChanged));
 
private static void OnButtonForegroundColorChanged(DependencyObject d,
            DependencyPropertyChangedEventArgs e)
{
     var applicationView = ApplicationView.GetForCurrentView();
     applicationView.TitleBar.ButtonForegroundColor = (Color)e.NewValue;
}
 
public Color ButtonBackgroundColor
{
     get { return (Color)GetValue(ButtonBackgroundColorProperty); }
     set { SetValue(ButtonBackgroundColorProperty, value); }
}
 
public static readonly DependencyProperty ButtonBackgroundColorProperty =
            DependencyProperty.Register("ButtonBackgroundColor",
            typeof(Color),
            typeof(TitleBarBehavior),
            new PropertyMetadata(false, OnButtonBackgroundColorChanged));
 
private static void OnButtonBackgroundColorChanged(DependencyObject d,
            DependencyPropertyChangedEventArgs e)
{
     var applicationView = ApplicationView.GetForCurrentView();
     applicationView.TitleBar.ButtonBackgroundColor = (Color)e.NewValue;
}

Hemos definido propiedades para modificar:

  • Título.
  • Color de fondo de la zona del título.
  • Color del título.
  • Color de fondo de la zona de botones.
  • Color de los botones.

Solo nos queda utilizar el Behavior en nuestra interfaz de usuario. Añadimos los namespaces necesarios:

xmlns:i="using:Microsoft.Xaml.Interactivity"
xmlns:behaviors="using:TitleBar.Behaviors"

Utilizamos el Behavior en nuestra Vista bindeando las propiedades para modificar el título y colores de gestión de la TitleBar:

<i:Interaction.Behaviors>
     <behaviors:TitleBarBehavior
          Title="Changed from Behavior!"
          BackgroundColor="{StaticResource RedColor}"
          ForegroundColor="{StaticResource WhiteColor}"
          ButtonBackgroundColor="{StaticResource BlueColor}"
          ButtonForegroundColor="{StaticResource WhiteColor}"/>
</i:Interaction.Behaviors>

Navegando a la segunda vista:

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

También podéis acceder al código fuente directamente en GitHub:

Ver GitHub

En futuros artículos veremos otras posibilidades como inyectar contenido XAML o añadir un botón volver directamente en la TitleBar. Recordar que cualquier tipo de duda o sugerencia la podéis dejar en los comentarios de la entrada.

Más información

[Evento] Windows 10 Developer Readiness Powered by MVPs

El evento

Windows 10 ha llegado como la culminación en el viaje hacia la convergencia en el desarrollo entre plataformas Windows. Ahora hablamos de Apps Universales
escritas una única vez con un código comun tanto para la lógica de
negocio como para la interfaz de usuario. Además, generamos un único paquete
que mantendrá una interfaz consistente y familiar para el usuario pero
adaptada a cada plataforma. Ante la inmensa cantidad de novedades
disponibles en la nueva plataforma Universal de Windows, nada mejor que
desgranarlas en un webcast.

Windows 10 Developer Readiness - Powered by MVPs

Este evento online es parte de una serie de webcasts que se realizarán a nivel mundial por parte del Programa MVP Award destinado a desarrolladores. El objetivo será aprender acerca de la nueva
Plataforma Universal de Windows además de tener sesiones de preguntas y
respuestas donde poder resolver todas las dudas posibles.

¿Te apuntas?

Fecha

El evento tendrá lugar el próximo Jueves, 11 de Junio de 19:00h a 22:00h. Tendremos una sesión de 3 horas de duración.

Ponentes

En las sucesivas sesiones técnicas rodeadas de la mayor cantidad de código y demos posibles estarán disponibles tres MVPs en el desarrollo de la plataforma Windows, Josué Yeray, Rafa Serna y un servidor.

Más información