Introducción a Xamarin.Forms: Personalización de la Interfaz de Usuario
() translation by (you can also view the original English article)
1. Preparando el Escenario
Al crear aplicaciones con Xamarin.Forms, sin duda te gustará la simplicidad de crear interfaces de usuario. Con Xamarin.Forms, puedes usar la misma terminología para los controles en varias plataformas.
Si bien este concepto puede ser muy poderoso, como diseñador o desarrollador, puede ser algo limitante. Puede parecer que nos vemos obligados a usar los controles de interfaz de usuario nativos que vienen con cada una de las plataformas sin la capacidad de agregar personalización. Este no es el caso.
Para entrar en el proceso de personalización de la interfaz de usuario para plataformas específicas, primero debes comprender el proceso de representación de Xamarin.Forms.
2. Renderizado de control
Cuando se trata de usar Xamarin.Forms para crear una interfaz de usuario para tu aplicación móvil multiplataforma, hay dos piezas importantes en el rompecabezas que debes entender.
Elemento
La primera pieza del rompecabezas es el elemento. Puedes pensar en un elemento como la definición agnóstica de plataforma de un control dentro de Xamarin.Forms. Si has leído la documentación, sabrás que estos controles también se denominan objetos View. Para ser aún más específicos, cada elemento de Xamarin.Forms deriva de la clase View
.
Estos elementos se utilizan para describir un elemento visual. Los elementos proporcionan una definición agnóstica de la plataforma de las características de cómo debe verse y comportarse el control. Un elemento por sí solo no puede crear un control que se muestre al usuario. Necesita ayuda. Aquí es donde entra en juego la segunda parte del proceso de renderizado, un renderizador.
Renderizador
Un renderizador entra en juego cuando se ejecuta la aplicación. El trabajo del renderizador es tomar el elemento agnóstico de la plataforma y transformarlo en algo visual para presentar al usuario.
Por ejemplo, si estuvieras usando un control Label
en el proyecto compartido, durante la ejecución de la aplicación, el marco Xamarin.Forms usaría una instancia de la clase LabelRenderer
para dibujar el control nativo. Si estás empezando a preguntarte cómo sucede esto desde un proyecto de código compartido, esa es una muy buena pregunta. La respuesta es que no.
Vamos a ilustrar esto con un ejemplo. Comienza abriendo Xamarin Studio o Visual Studio. El proceso y los conceptos son los mismos para ambos. Si usas Xamarin Studio, no hay compatibilidad con proyectos de Windows Phone, por lo que solo crearás tres proyectos en la solución. Si usas Visual Studio, crearás cuatro proyectos.
En Visual Studio, crea un nuevo proyecto y selecciona la familia de proyectos Aplicaciones Móviles a la izquierda y elije la plantilla de proyecto Aplicación en Blanco (Xamarin.Forms Portable) a la derecha. Puedes nombrar tu proyecto como desees, pero si deseas seguirme, usa el nombre Personalización y haz clic en Aceptar.
Ahora, dependiendo de tu IDE, deberías ver tres o cuatro proyectos en tu solución. Si expandes la carpeta Referencias en el proyecto de Personalización (Portátil), verás una referencia de ensamblado a Xamarin.Forms.Core. Aquí es donde se definen todos los diferentes elementos para que los uses en tu proyecto de interfaz de usuario compartida. Nada fuera de lo común allí.
Si abres cada uno de los proyectos específicos de la plataforma y expandes tus carpetas Referencias, verás que cada uno contiene una implementación específica de la plataforma de esa biblioteca Xamarin.Forms, denominada Xamarin.Forms.Platform.Android, Xamarin.Forms.Platform.iOS y Xamarin.Forms.Platform.WP8 respectivamente.
Es en estos ensamblados donde encontrarás los representadores para cada uno de los elementos Xamarin.Forms. Ahora estás comenzando a ver el diseño del proceso. Los elementos independientes de la plataforma, u objetos View
, están en el proyecto de código compartido, pero todos los representadores específicos para los elementos están en los proyectos específicos de la plataforma.
Esto significa que para cada uno de los elementos que utilices, habrá dos renderizadores creados en Xamarin Studio y tres en Visual Studio. Ahora que ves cómo se estructura esto en Xamarin.Forms, la siguiente pregunta lógica suele ser: "¿Cuándo debo usar personalizaciones?".
3. Cuándo personalizar
Definitivamente hay un buen número de propiedades y características que se definen dentro de los elementos Xamarin.Forms que se pueden usar para personalizar el control final en cada una de las plataformas. Dicho esto, sin embargo, no todas las personalizaciones disponibles en cada una de las plataformas existen en Xamarin.Forms. Siendo ese el caso, hay dos escenarios principales en los que querrás crear personalizaciones.
El primer escenario en el que se necesitarán personalizaciones es cuando deseas crear un control completamente personalizado. Digamos que deseas crear un control de calendario o tal vez algún tipo de control de gráficos. Desafortunadamente nada de eso existe hoy en día en Xamarin.Forms, lo que no quiere decir que nunca lo hará.
Esta es definitivamente una situación en la que tendrás que comenzar desde el principio y crear todo desde cero. Deberás definir el elemento que vas a utilizar para describir las características del control de una manera independiente de la plataforma. Luego, también deberás crear un renderizador personalizado para cada una de las plataformas que deseas admitir.
Dependiendo de lo que estés construyendo, este puede ser un proyecto bastante extenso. Siendo ese el caso, lo guardaré para otro tutorial en sí mismo. En cambio, en este tutorial, nos centraremos en el segundo escenario en el que necesitarás cierta personalización.
La segunda situación en la que necesitarás cierta personalización es cuando un elemento incorporado no admite una característica específica de una plataforma que deseas admitir. Un ejemplo de esto estaría en el control Label
. En Xamarin.Forms, no hay ningún mecanismo, o propiedad, que te permita crear el equivalente en cada una de las plataformas para que el texto esté en negrita o cursiva. Esto puede parecer un escenario muy simple, pero encontrarás que el proceso básico de hacer que este cambio esté disponible en el elemento y hacer que el renderizador lo entienda será el mismo aquí que en algunos de los escenarios más complejos.
Con el segundo escenario en mente, tienes dos opciones. Puedes reemplazar el renderizador existente para una plataforma específica (o para todas las plataformas) y crear su propia funcionalidad y lógica de dibujo para todas las capacidades del elemento. Como alternativa, puedes crear tu propio elemento que se derive del elemento existente y asociar ese nuevo elemento con un representador personalizado. De esta manera, conservarás toda la lógica predeterminada y las capacidades de representación del elemento base y lo personalizas como desees. Esta será la ruta que tomemos para este ejemplo. Ahora, veamos cómo agregar esta funcionalidad a nuestro propio proyecto.
4. Agregar personalización
Comencemos este proceso configurando la estructura básica de nuestra aplicación para que podamos ver nuestra línea de base y luego hacer cambios. Comienza abriendo el archivo App.cs en el proyecto Personalización (Portátil) en el Explorador de Soluciones. Modifica el método GetMainPage
para que tenga el siguiente aspecto:
1 |
public static Page GetMainPage() { |
2 |
var iLabel = new Label { |
3 |
TextColor = Color.Black, |
4 |
Text = "I want to be italicized!", |
5 |
HorizontalOptions = LayoutOptions.CenterAndExpand |
6 |
};
|
7 |
var bLabel = new Label |
8 |
{
|
9 |
Text = "I want to be bold!", |
10 |
TextColor = Color.Black, |
11 |
HorizontalOptions = LayoutOptions.CenterAndExpand |
12 |
};
|
13 |
var bothLabel = new Label |
14 |
{
|
15 |
Text = "I want to be italicized and bold!", |
16 |
TextColor = Color.Black, |
17 |
HorizontalOptions = LayoutOptions.CenterAndExpand |
18 |
};
|
19 |
return new ContentPage |
20 |
{
|
21 |
BackgroundColor = Color.White, |
22 |
Content = new StackLayout { |
23 |
Padding = 100, |
24 |
Spacing = 100, |
25 |
Children = { iLabel, bLabel, bothLabel } |
26 |
}
|
27 |
};
|
28 |
}
|
Como puedes ver aquí, hemos creado tres controles de Label
simples. Uno quiere estar en cursiva, uno quiere ser audaz, y el tercero es codicioso y quiere ser ambos. Si tuvieras que ejecutar esta aplicación en iOS, Android y Windows Phone, se verían algo como esto:
iOS

Android
Windows Phone
Como puedes ver, no quieren ser tan aburridos. Bueno, no te quedes sentado allí, ayúdalos.
Paso 1: Crear un Nuevo Elemento
Lo primero que debemos hacer es crear un nuevo elemento que podamos usar para proporcionar personalizaciones adicionales al control Label
existente. Comienza agregando una nueva clase a tu proyecto de Personalización (Portátil) y nombralo StyledLabel. Reemplaza su contenido por el siguiente:
1 |
public enum StyleType { |
2 |
Italic, |
3 |
Bold, |
4 |
BoldItalic
|
5 |
}
|
6 |
|
7 |
public class StyledLabel : Label |
8 |
{
|
9 |
public StyleType Style { get; set; } |
10 |
}
|
Definimos una enumeración y una clase muy simples. Hemos definido la enumeración para permitir valores en cursiva, negrita y negrita más cursiva. A continuación, creamos una clase StyledLabel
que deriva de la clase base Label
y agregamos una nueva propiedad, Style
, para mantener el estilo apropiado que queremos aplicar al control.
Para asegurarnos de que todo sigue funcionando, y debería, modifiquemos el archivo App.cs una vez más y reemplacemos los elementos Label
en nuestro primer ejemplo con nuestros nuevos elementos StyledLabel
. Dado que la clase StyleLabel
hereda de la clase Label
, todo debería seguir funcionando.
1 |
public static Page GetMainPage() { |
2 |
var iLabel = new StyledLabel { |
3 |
TextColor = Color.Black, |
4 |
Text = "I want to be italicized!", |
5 |
HorizontalOptions = LayoutOptions.CenterAndExpand, |
6 |
Style = StyleType.Italic |
7 |
};
|
8 |
var bLabel = new StyledLabel |
9 |
{
|
10 |
Text = "I want to be bold!", |
11 |
TextColor = Color.Black, |
12 |
HorizontalOptions = LayoutOptions.CenterAndExpand, |
13 |
Style = StyleType.Bold |
14 |
};
|
15 |
var bothLabel = new StyledLabel |
16 |
{
|
17 |
Text = "I want to be italicized and bold!", |
18 |
TextColor = Color.Black, |
19 |
HorizontalOptions = LayoutOptions.CenterAndExpand, |
20 |
Style = StyleType.BoldItalic |
21 |
};
|
22 |
return new ContentPage |
23 |
{
|
24 |
BackgroundColor = Color.White, |
25 |
Content = new StackLayout { |
26 |
Padding = 100, |
27 |
Spacing = 100, |
28 |
Children = { iLabel, bLabel, bothLabel } |
29 |
}
|
30 |
};
|
31 |
}
|
Una vez más, aquí están los resultados de este cambio.
iOS

Android
Windows Phone
Como puedes ver, nada ha cambiado. Ahora que tenemos un nuevo elemento personalizado, es el momento de crear los renderizadores personalizados para encargarse de los controles nativos.
Paso 2: Renderizador de Android
El primer paso para crear un renderizador es agregar una nueva clase a la plataforma a la que se dirige. Comenzaremos con el proyecto Xamarin.Android. Dentro de este proyecto, crea un nuevo archivo de clase y lo nombras StyledLabelRenderer y reemplaza su contenido por el siguiente:
1 |
using Android.Graphics; |
2 |
using Customization; |
3 |
using Customization.Droid; |
4 |
using Xamarin.Forms; |
5 |
using Xamarin.Forms.Platform.Android; |
6 |
|
7 |
[assembly: ExportRenderer(typeof(StyledLabel), typeof(StyledLabelRenderer))] |
8 |
|
9 |
namespace Customization.Droid |
10 |
{
|
11 |
public class StyledLabelRenderer : LabelRenderer { |
12 |
protected override void OnElementChanged( ElementChangedEventArgs<Label> e ) { |
13 |
base.OnElementChanged( e ); |
14 |
|
15 |
var styledLabel = (StyledLabel)Element; |
16 |
|
17 |
switch (styledLabel.Style) |
18 |
{
|
19 |
case StyleType.Bold: |
20 |
Control.SetTypeface(null, TypefaceStyle.Bold); |
21 |
break; |
22 |
case StyleType.Italic: |
23 |
Control.SetTypeface(null, TypefaceStyle.Italic); |
24 |
break; |
25 |
case StyleType.BoldItalic: |
26 |
Control.SetTypeface(null, TypefaceStyle.BoldItalic); |
27 |
break; |
28 |
}
|
29 |
|
30 |
}
|
31 |
}
|
32 |
}
|
Echemos un vistazo más de cerca a este bloque de código.
1 |
[assembly: ExportRenderer(typeof(StyledLabel), typeof(StyledLabelRenderer))] |
Comenzamos con un atributo de assembly
especial que indica a Xamarin.Forms que use esta clase StyledLabelRenderer
como representador cada vez que intenta representar objetos StyledLabel
. Esto es necesario para que las personalizaciones funcionen correctamente.
Al igual que cuando creamos un nuevo elemento StyledLabel
, heredado de la clase Label
, haremos que nuestra nueva clase StyledLabelRenderer
herede de la clase LabelRenderer
. Esto nos permitirá mantener la funcionalidad existente por lo que solo tendremos que anular lo que queremos cambiar o personalizar.
Para aplicar nuestro nuevo formato, vamos a tener que saltar al proceso de renderizado y lo hacemos a través del método OnElementChanged
. En este método, podemos hacer todas nuestras personalizaciones.
Al hacer tus personalizaciones, hay dos propiedades muy importantes que utilizarás. Primero, deberás obtener una referencia al elemento original que creaste y que se está representando en nuestro método de renderizado personalizado. Para ello, utiliza la propiedad Element
. Este es un objeto genérico, por lo que tendrás que convertirlo en cualquier tipo que estés representando. En este caso, se trata de un StyledLabel
.
1 |
var styledLabel = (StyledLabel)Element; |
La segunda propiedad importante que necesitas es la propiedad Control
. Esta propiedad contiene una referencia con tipo al control nativo de la plataforma. En este caso, dado que has heredado de la clase LabelRenderer
, el código ya sabe que el Control
en este caso es un TextView
.
A partir de este punto, utilizarás una lógica simple para determinar qué personalización realizar y aplicar las personalizaciones nativas adecuadas. En este caso, utilizarás el mecanismo de Android para modificar el tipo de letra de un TextView
mediante el método SetTypeface
.
1 |
switch (styledLabel.Style) |
2 |
{
|
3 |
case StyleType.Bold: |
4 |
Control.SetTypeface(null, TypefaceStyle.Bold); |
5 |
break; |
6 |
case StyleType.Italic: |
7 |
Control.SetTypeface(null, TypefaceStyle.Italic); |
8 |
break; |
9 |
case StyleType.BoldItalic: |
10 |
Control.SetTypeface(null, TypefaceStyle.BoldItalic); |
11 |
break; |
12 |
}
|
Si tuvieras que ejecutar esta aplicación ahora, deberías ver algo como lo siguiente en el emulador de Android, que es exactamente lo que buscamos.
Paso 3: Renderizador de iOS
El proceso de creación del renderizador de iOS es exactamente el mismo hasta el punto de anular el método OnElementChanged
. Comienza creando una nueva clase en su proyecto Customization.iOS. Dale el nombre de StyledLabelRenderer y reemplaza el contenido por el siguiente:
1 |
using Customization; |
2 |
using Customization.iOS; |
3 |
using MonoTouch.UIKit; |
4 |
using Xamarin.Forms; |
5 |
using Xamarin.Forms.Platform.iOS; |
6 |
|
7 |
[assembly: ExportRenderer(typeof(StyledLabel), typeof(StyledLabelRenderer))] |
8 |
|
9 |
namespace Customization.iOS |
10 |
{
|
11 |
public class StyledLabelRenderer : LabelRenderer |
12 |
{
|
13 |
protected override void OnElementChanged(ElementChangedEventArgs<Label> e) |
14 |
{
|
15 |
base.OnElementChanged(e); |
16 |
|
17 |
var styledLabel = (StyledLabel)Element; |
18 |
|
19 |
switch (styledLabel.Style) |
20 |
{
|
21 |
case StyleType.Bold: |
22 |
Control.Font = UIFont.BoldSystemFontOfSize( 16.0f ); |
23 |
break; |
24 |
case StyleType.Italic: |
25 |
Control.Font = UIFont.ItalicSystemFontOfSize( 16.0f ); |
26 |
break; |
27 |
case StyleType.BoldItalic: |
28 |
Control.Font = UIFont.FromName( "Helvetica-BoldOblique", 16.0f ); |
29 |
break; |
30 |
}
|
31 |
}
|
32 |
}
|
33 |
}
|
Como ves, todo es exactamente igual. Tiene el mismo atributo de assembly
, estás anulando el mismo método OnElementChanged
, estás concediendo la propiedad Element
a un StyledLabel
y tienes el mismo shell de una instrucción switch
para trabajar a través de la propiedad Style
.
La única diferencia se produce en el lugar donde se aplica el estilo al control UILabel
nativo.
1 |
switch (styledLabel.Style) |
2 |
{
|
3 |
case StyleType.Bold: |
4 |
Control.Font = UIFont.BoldSystemFontOfSize( 16.0f ); |
5 |
break; |
6 |
case StyleType.Italic: |
7 |
Control.Font = UIFont.ItalicSystemFontOfSize( 16.0f ); |
8 |
break; |
9 |
case StyleType.BoldItalic: |
10 |
Control.Font = UIFont.FromName( "Helvetica-BoldOblique", 16.0f ); |
11 |
break; |
12 |
}
|
La forma de hacer que la propiedad Font
de UILabel
esté en negrita o cursiva en iOS es a través de un método auxiliar estático en la clase UIFont
denominada BoldSystemFontOfSize
o ItalicSystemFontOfSize
. Eso funcionará en el caso de una fuente en negrita o una fuente en cursiva, pero no en ambas. Si intentas aplicar ambos a un UILabel
, solo se renderizará el último.
Para conseguir ambos estilos, haremos un poco de trampa y utilizaremos una fuente incorporada en iOS llamada Helvetica-BoldOblique. Esta fuente tiene negrita y cursiva incorporadas, por lo que no tenemos que hacerlas individualmente.
Ejecutar esto en el simulador de iOS te dará el siguiente resultado:

Paso 4: Renderizador de Windows Phone
Por último, llegamos a Windows Phone. Como ya habrás adivinado, el proceso es exactamente el mismo. Crea una nueva clase en el proyecto Customization.WinPhone, dale el nombre de StyledLabelRenderer y reemplaza el contenido por el siguiente:
1 |
using System.Windows; |
2 |
using Customization; |
3 |
using Customization.WinPhone; |
4 |
using Xamarin.Forms; |
5 |
using Xamarin.Forms.Platform.WinPhone; |
6 |
|
7 |
[assembly: ExportRenderer(typeof(StyledLabel), typeof(StyledLabelRenderer))] |
8 |
|
9 |
namespace Customization.WinPhone |
10 |
{
|
11 |
public class StyledLabelRenderer : LabelRenderer |
12 |
{
|
13 |
protected override void OnElementChanged( ElementChangedEventArgs<Label> e ) { |
14 |
base.OnElementChanged( e ); |
15 |
|
16 |
var styledLabel = (StyledLabel) Element; |
17 |
|
18 |
switch ( styledLabel.Style ) { |
19 |
case StyleType.Bold: |
20 |
Control.FontWeight = FontWeights.Bold; |
21 |
break; |
22 |
case StyleType.Italic: |
23 |
Control.FontStyle = FontStyles.Italic; |
24 |
break; |
25 |
case StyleType.BoldItalic: |
26 |
Control.FontStyle = FontStyles.Italic; |
27 |
Control.FontWeight = FontWeights.Bold; |
28 |
break; |
29 |
}
|
30 |
}
|
31 |
}
|
32 |
}
|
Una vez más, todo es igual excepto por la lógica. En este caso, para que el texto quede en cursiva, establece la propiedad FontStyle
de TextBlock
en Italic
. A continuación, para que el texto esté en negrita, establece la propiedad FontWeight
en Bold
. Si deseas aplicar ambos, simplemente configura ambos.
La ejecución de esta aplicación en el emulador de Windows Phone te dará el siguiente resultado:
Ahora has creado con éxito un elemento multiplataforma totalmente funcional, personalizado y que se representa perfectamente en las tres plataformas. Ahora deberías sentirte listo para enfrentarte al mundo. Bueno, casi.
El proceso que hemos seguido a lo largo de este tutorial es completamente válido y en la mayoría de los casos va a funcionar a la perfección. Sin embargo, hay un caso muy específico en el que nos perderemos alguna funcionalidad si usamos ese enfoque. Ese caso es vinculante de datos en XAML.
5. XAML y Enlace de Datos
Una de las características interesantes de Xamarin.Forms es el hecho de que puedes usar XAML y el enlace de datos tal como lo harías si estuvieras creando una aplicación de Windows Phone, WPF o Silverlight. Desafortunadamente, el enlace de datos y XAML están más allá del alcance de este tutorial, pero te recomiendo que leas más sobre este tema en la página XAML para Xamarin.Forms.
Paso 1: Crear la página XAML
Comencemos por crear una página XAML simple que duplique la interfaz de usuario que hemos creado previamente en el código. Comienza agregando un nuevo archivo al proyecto Customizations (Portable), seleccionando el tipo de archivo Página XAML Forms y asignándole un nombre de StyledLabelPage.
Una vez creado el archivo, reemplaza el contenido por el siguiente:
1 |
<?xml version="1.0" encoding="utf-8" ?>
|
2 |
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" |
3 |
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" |
4 |
xmlns:local="clr-namespace:Customization;assembly=Customization" |
5 |
x:Class="Customization.StyledLabelPage"> |
6 |
<StackLayout BackgroundColor="White" Spacing="100" Padding="100"> |
7 |
<local:StyledLabel Text="I want to be italicized" TextColor="Black" HorizontalOptions="CenterAndExpand" Style="Italic" /> |
8 |
<local:StyledLabel Text="I want to be bold" TextColor="Black" HorizontalOptions="CenterAndExpand" Style="Bold" /> |
9 |
<local:StyledLabel Text="I want to be italicized and bold" TextColor="Black" HorizontalOptions="CenterAndExpand" Style="BoldItalic" /> |
10 |
</StackLayout>
|
11 |
</ContentPage>
|
Este XAML creará exactamente la misma página con la que hemos estado trabajando antes. Ten en cuenta la adición de la declaración de espacio de nombres xmlns:local
en la parte superior del archivo, así como el prefijo local:
antes de cada referencia a los objetos StyledLabel
. Sin estos, el analizador XAML no sabrá qué es un StyledLabel
y, en última instancia, no podrá ejecutarse.
Para ejecutar esto, deberás realizar dos pequeñas modificaciones. Primero, abre el archivo App.cs y modifica el método GetMainPage
para que tenga este aspecto:
1 |
public static Page GetMainPage() { |
2 |
return new StyledLabelPage(); |
3 |
}
|
En segundo lugar, abre el archivo StyledLabelPage.xaml.cs y cámbialo para que se vea así:
1 |
public partial class StyledLabelPage : ContentPage |
2 |
{
|
3 |
public StyledLabelPage() |
4 |
{
|
5 |
InitializeComponent(); |
6 |
}
|
7 |
}
|
Ahora, cuando ejecutes tus aplicaciones, deberías obtener los mismos resultados en las tres plataformas. Bastante limpio, ¿eh?
iOS

Android
Windows Phone
Paso 2: Agregar enlace de datos
Si estás familiarizado con el concepto del patrón View View-Model pattern (MVVM), sabrás que una de sus características principales es el enlace de datos. De hecho, este patrón fue diseñado en torno al uso de XAML.
El enlace de datos es el proceso de permitir que las propiedades de dos objetos se vinculan entre sí para que un cambio en uno cree un cambio en el otro. El proceso de enlace de datos dentro de XAML se logra mediante el uso de la Extensión de Marcado de Enlace.
Las extensiones de marcado no son una característica de Xamarin.Forms, ni siquiera de XAML. En realidad, es una característica de XML que permite aplicar funcionalidad adicional al proceso de establecer el valor de un atributo en un elemento.
Por ejemplo, echemos un vistazo más de cerca al primer elemento StyledLabel
en el ejemplo anterior.
1 |
<local:StyledLabel Text="I want to be italicized" TextColor="Black" HorizontalOptions="CenterAndExpand" Style="Italic" /> |
El problema con este marcado es que todas las propiedades (atributos) se asignan explícitamente. Esto crea un diseño bastante inflexible. Entonces, ¿qué sucede si por alguna razón durante la ejecución de nuestra aplicación, queremos cambiar el atributo Style
para que tenga un valor de Bold
? Bueno, en nuestro archivo de código subyacente, tendríamos que observar un evento, capturar ese evento, obtener esta instancia del elemento StyledLabel
y modificar este valor de atributo. Eso suena como mucho trabajo. ¿No sería bueno si pudiéramos facilitar ese proceso? Bueno, podemos.
Extensión de Marcado de Enlace
La forma en que puedes hacer que este diseño sea más flexible para la modificación es mediante el uso de la extensión de marcado Binding
. La forma de usar esta extensión es modificando el marcado para que tenga el siguiente aspecto:
1 |
<local:StyledLabel Text="I want to be italicized" TextColor="Black" HorizontalOptions="CenterAndExpand" Style="{Binding FirstStyle}" /> |
Como puedes ver, hemos cambiado el valor de la propiedad Style
a {Binding FirstStyle}
. El uso de una extensión de marcado se suele decir mediante el uso de llaves rizadas {}.
Esto significa que lo que esté contenido dentro de los brackets rizados va a ser una extensión de marcado.
En este caso, estamos utilizando la extensión Binding.
La segunda parte de esta extensión es el nombre de una propiedad que queremos enlazar a esta propiedad (atributo). En este caso, lo llamaremos FirstStyle.
Eso aún no existe, pero nos encargaremos de eso en un momento. Primero, actualicemos completamente este archivo para aprovechar el enlace de datos.
1 |
<?xml version="1.0" encoding="utf-8" ?>
|
2 |
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" |
3 |
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" |
4 |
xmlns:local="clr-namespace:Customization;assembly=Customization" |
5 |
x:Class="Customization.StyledLabelPage"> |
6 |
<StackLayout BackgroundColor="White" Spacing="100" Padding="100"> |
7 |
<local:StyledLabel Text="I want to be italicized" TextColor="Black" HorizontalOptions="CenterAndExpand" Style="{Binding FirstStyle}" /> |
8 |
<local:StyledLabel Text="I want to be bold" TextColor="Black" HorizontalOptions="CenterAndExpand" Style="{Binding SecondStyle}" /> |
9 |
<local:StyledLabel Text="I want to be italicized and bold" TextColor="Black" HorizontalOptions="CenterAndExpand" Style="{Binding ThirdStyle}" /> |
10 |
</StackLayout>
|
11 |
|
12 |
</ContentPage>
|
BindingContext
Dado que estamos creando un enlace, por definición estamos tratando de vincular este atributo XAML a otra cosa que permita que estas dos propiedades compartan sus datos. Para ello, primero deberás crear una clase que contenga propiedades con los mismos nombres que estamos usando en el ejemplo XAML anterior.
Crea una nueva clase dentro del proyecto Customizations (Portable) y asígnale el nombre SampleStyles y reemplaza el contenido por el siguiente:
1 |
public class SampleStyles |
2 |
{
|
3 |
public StyleType FirstStyle { get; set; } |
4 |
public StyleType SecondStyle { get; set; } |
5 |
public StyleType ThirdStyle { get; set; } |
6 |
}
|
Esta es una clase muy simple que contiene tres propiedades de tipo StyleType
con los mismos nombres que usamos en nuestro Bindin
g de los atributos. Ahora tenemos el XAML usando la extensión de marcado Binding
y una clase que contiene propiedades con el mismo nombre que vemos en los enlaces en el XAML. Solo necesitamos pegamento para juntarlos. Ese pegamento es el BindingContext
.
Para vincular las propiedades de estos objetos, necesitamos asignar una instancia de la clase SampleStyles
a la propiedad BindingContext
de StyledLabelPage
. Abre el archivo StyledLabelPage.xaml.cs y modifica el constructor para que sea similar al siguiente:
1 |
public StyledLabelPage() |
2 |
{
|
3 |
InitializeComponent(); |
4 |
BindingContext = new SampleStyles { |
5 |
FirstStyle = StyleType.Italic, |
6 |
SecondStyle = StyleType.Bold, |
7 |
ThirdStyle = StyleType.BoldItalic |
8 |
};
|
9 |
}
|
En teoría, si ejecutaras tu aplicación, el archivo XAML se rellenará con los valores de nuestras propiedades SampleStyles
y todo se representaría en la pantalla como vimos antes. Lamentablemente no es así. Terminas obteniendo una excepción en tiempo de ejecución que se ve así:
Si miras Información adicional, verás que el problema es que No se encontró ninguna propiedad de estilo de nombre. Esto es el resultado de la forma en que creamos el StyledLabe
l al principio. Para aprovechar el enlace de datos, las propiedades deben ser del tipo BindableProperty
. Para ello, tendremos que hacer una pequeña modificación en nuestra clase StyledLabel
.
1 |
public class StyledLabel : Label { |
2 |
public static readonly BindableProperty StyleProperty = BindableProperty.Create<StyledLabel, StyleType>( p => p.Style, StyleType.None ); |
3 |
|
4 |
public StyleType Style { |
5 |
get { return (StyleType)base.GetValue( StyleProperty ); } |
6 |
set { base.SetValue(StyleProperty, value);} |
7 |
}
|
8 |
}
|
Como puedes ver, hemos agregado una propiedad estática llamada StyleProperty
de tipo BindableProperty
. Luego le asignamos el resultado de un CreateMethod
que define al dueño de la propiedad con la que estamos trabajando.
La propiedad es Style
, pero el propietario es StyledLabel
. El segundo parámetro genérico es el tipo devuelto de la propiedad, que es StyleType
. Entonces, el único argumento que estamos proporcionando al método es una expresión que define lo que se devuelve y un valor predeterminado. En nuestro caso, estamos devolviendo el valor de la propiedad de instancia Style
y el valor predeterminado será None
o no styling.
A continuación, debemos modificar la implementación de la propiedad Style
para aplazar la funcionalidad de obtención y configuración a la clase base, de modo que BindingProperty
se actualice correctamente si cambia el valor de la propiedad Style
.
Ahora, si volvieras a ejecutar tu aplicación, deberías ver que todo funciona como se esperaba.
iOS

Android
Windows Phone
Conclusión
En este tutorial, aprendiste sobre un concepto muy importante en el mundo de Xamarin.Forms, la personalización. La personalización es una de las características clave que les permite destacarse de la competencia.
Saber cómo, cuándo y dónde personalizar es una habilidad muy importante para tener como desarrollador móvil. Espero que encuentres estas habilidades útiles y seas capaz de darles un buen uso en tu próximo proyecto.