[Universal Apps/ Xamarin.Forms] XCC. Compilación condicional en XAML

Introducción

Las condiciones de compilación son un proceso que nos permiten
definir directivas de compilación que provocarán que partes del código
sean compiladas y otras ignoradas.

Utilizamos las directivas #if, #else y #endif
para establecer código distinto ante directivas de compilación
diferente. Muy utilizados para añadir código que solo añadiremos en DEBUG
y en el desarrollo de aplicaciones móviles, para poder añadir en la
misma clase partes de código diferente entre distintas plataformas.

Técnica disponible para añadir bloques de código específico por
plataforma en nuestro código C# por ejemplo, en el desarrollo de
aplicaciones Universales Windows. Sin embargo, en el caso de vistas,
debemos utilizar otro tipo de técnicas (VisualStates, separar vistas en
ficheros diferentes, etc.) ya que no contamos con compilación
condicional en XAML

XCC. XAML Conditional Compilation

El proyecto XAML Conditional Compilation (XCC) de Koen Zwikstra
nos define una serie de namespaces XAML que nos permiten trabajar de
una forma similar a como lo hacemos en C# con directivas de compilación.

XCC se convierte en una opción muy útil cuando trabajamos con vistas
XAML en aplicaciones Universales Windows que deseamos compartir o en
Xamarin.Forms. Podremos especificar elementos visuales solo para una
plataforma e incluso el mismo elemento definirlo de forma diferente
segun la paltaforma.

Aplicaciones Universales

Comenzamos creando un nuevo proyecto:

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 sera muy sencillo. Nuestra aplicación de ejemplo
tendra diferentes elementos que añadiremos especificándo la plataforma o
bien creando elementos comunes a ambas plataformas pero con propiedades
específicas.

A continuación, añadiremos XCC. La librería la tenemos disponible en NuGet por lo que podemos instalarlo usando Nuget Package Manager. En las referencias de la solución hacemos clic derecho y seleccionamos la opción Manage NuGet Packages for Solution…

En la ventana modal que nos aparece, en la parte superior derecha donde podemos realizar una búsqueda, buscamos por “XCC”:

Seleccionamos el elemento disponible y pulsamos el botón Install.
Tras un breve periodo donde se procede a descargar e incluir las
librerías en las referencias de cada proyecto, tendremos lo necesario
para comenzar a trabajar con directivas de compilación en XAML.

Lo primero que debemos hacer es definir en nuestra vista los espacio
de nombres que utilizaremos para identificar cada plataforma:

xmlns:debug="condition:DEBUG"
xmlns:release="condition:!DEBUG"
xmlns:win81="condition:WINDOWS_APP"
xmlns:wp81="condition:WINDOWS_PHONE_APP"

Los atributos xmlns:win81 y xmlns:wp81
definen los namespaces que utilizaremos para realizar compilación
condicional por plataforma con los elementos y atributos XML. También
hemos definido los atributos xmlns:debug y xmlns:release que nos permiten distinguir elementos y atributos entre DEBUG y RELEASE.

Comenzamos utilizando los espacio de nombre definidos previamente:

<debug:TextBlock    
     Text="Solo visible en DEBUG" />
             
<release:TextBlock
     Text="Solo visible en RELEASE" />

Hemos definido dos controles para mostrar texto con los atributos xmlns:debug y xmlns:release respectivamente. El primero de ellos solo se compilará y aparecerá en modo DEBUG mientras que el segundo de ellos solo lo hará en RELEASE.

NOTA: El diseñador de Visual Studio ignora los prefijos de compilación condicional que utilizamos.

De la misma forma que lo utilizamos con elementos en su totalidad lo podemos hacer con atributos de un elemento:

<!-- Rojo en DEBUG, Verde en RELEASE -->     
<TextBlock Text="Siempre visible"
     debug:Foreground="Red"
     release:Foreground="Green" />

En el ejemplo superior el TextBlock se compilará para ambas plataformas. Sin embargo, el color del texto será rojo en DEBUG y verde en RELEASE.

Muy interesante sin duda lo visto hasta ahora pero la parte más
interesante es el uso de los espacio de nombre que nos permiten hacer
distinciones entre las plataformas.

 <!-- Win Button -->
 <win81:Button                
     Content="Windows" />
            
 <!-- Phone Button -->
 <wp81:Button
     Content="Windows Phone" />

En el trozo de XAML anterior, el primero botón solo aparecerá en la
App Windows Store mientras que el segundo hara lo propio solo en la App
Windows Phone.

Al igual que con las directivas de compilación para distinguir entre DEBUG y RELEASE, podemos establecer atributos (propiedades) distintas segun la plataforma:

<Button
     Content="Botón"
     win81:Background="Blue"
     wp81:Background="Green"/>

El resultado en Windows Store:

Windows Phone:

NOTA: XCC no modifica los archivos XAML, crea archivos XAML temporales en la carpeta obj y redirige al compilador XAML a ellos.

Extremadamente útil en vistas no complejas donde mostrar de forma diferente elementos como publicidad, algun DataTemplate, ocultar controles, etc. de una forma muy sencilla.

Al igual que en el uso de directivas de compilación en código C#, la recomendación
general es la misma, no conviene realizar un uso excesivo de la
técnica. Si tenemos una vista compleja llena de elementos marcados con
directivas de compilación se volvería excesivamente compleja y añadiría
dificultad a la hora de realizar el mantenimiento de la misma. Según las
características de la vista nos encontraremos situaciones en als que
conviene utilizar directivas de compilación y otras en las que lo mejor
sea separar en dos ficheros diferentes.

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

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

Ver GitHub

Xamarin

XCC también esta disponible para Xamarin.Forms. Para probar las posibilidades crearemos un nuevo proyecto Xamarin.Forms:

En el proyecto Shared o PCL crearemos una vista principal XAML:

A continuación, añadiremos XCC utilizando NuGet de igual forma que hicimos con la Aplicación Universal Windows.

Lo primero que debemos hacer es definir en nuestra vista los espacio
de nombres que utilizaremos para identificar cada plataforma:

xmlns:android="condition:__ANDROID__"
xmlns:ios="condition:__IOS__"
xmlns:wp="condition:WINDOWS_PHONE"

Los atributos xmlns:android, xmlns:ios y xmlns:wp definen los espacio de nombres que utilizaremos para definir condiciones de compilación en elementos y atributos XML.

Podemos definir con facilidad elementos visuales específicos por plataforma:

<android:Label
     Text="Android" />
 
<ios:Label
     Text="iOS" />
 
<wp:Label
     Text="Windows Phone" />

Por supuesto, también podemos utilizar directivas de compilación con atributos (propiedades):

<!-- Android: Verde, iOS: Azul, Windows Phone: Rojo -->
<Label Text="Label"
     android:TextColor="Green"
     ios:TextColor="Blue"
     wp:TextColor="Red" />

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

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

Ver GitHub

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

Más información

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *