[Tips and Tricks] Utilizando Code Snippets en Visual Studio para macOS

Introducción

Como desarrolladores, a la hora de programar en determinadas ocasiones escribimos código repetitivo. Si nos centramos en el desarrollo de aplicaciones Xamarin.Forms desde Visual Studio para macOS, por ejemplo; a la hora de definir ViewModels tenemos código repetitivo como la definición de propiedades o comandos.

public string Name
{
     get => _name;
     set => SetProperty(ref _name, value);
}

public string SurName
{
     get => _surname;
     set => SetProperty(ref _surname, value);
}

¿Y si tenemos una forma de mejorar nuestra productividad a la hora de escribir código repetitivo / similar?

Creando Code Snippets

En Visual Studio para macOS cuenta con una solución para este problema, code snippets.

¿Qué es un code snippet?

Un snippet de código es una pieza de texto guardada como plantilla, reutilizable y que puede contar con argumentos reemplazables por valores al ser utilizados.

Veamos un ejemplo:

private $type$ $field$;

public $type$ $property$
{
     get => $field$;
     set => SetProperty(ref $field$, value);
}

Cada parte del código rodeada por $, representa un argumento que se puede reemplazar por un valor. En el ejemplo anterior usamos tres argumentos para controlar el tipo de la propiedad, el nombre de la variable y el nombre de la propiedad.

Bien, pero…¿y cómo creamos code snnipets?.

Accedemos a la ventana de Preferencias de Visual Studio para macOS. Y desde aquí al editor de Code Snippets.

Code Snippets

Debemos pulsar sobre el botón Add para añadir un nuevo snippet.

Nuevo Snippet

Tenemos que rellenar:

  • Shortcut: Una de las partes más importantes. Es el atajo que utilizaremos con IntelliSense para utilizar el snippet.
  • Group: Representa la carpeta donde se guardará el snippet dentro del panel de preferencias de Code Snippet.
  • Description: La descripción del snippet. Esta descripción aparecerá en el tooltip al utilizarlo.
  • Mime: El mime-type del lenguaje de código que el code snippet soporta.
  • Template Text: El contenido del snippet de código.

Nuestro snippet!

Utilizando Code Snippets

Llega el momento que esperábamos!. Escribimos el valor del Shortcut de nuestro snippet.

Comenzamos a usar el Snippet

Pulsamos el tabulador y…

Voila!. Basta con definir el tipo y nombre de variable y propiedad para tener una propiedad pública completa en la ViewModel.

Basta ya con definir tipo y nombres

Los Code Snippets son fáciles de crear y usar pero ayudan a acelerar la creación de código aumentando nuestra productivad.

¿Usabas los snippets?. Recuerda, puedes dejar cualquier duda en los comentarios del artículo.

Más información

[Tips and Tricks] Corregir “Xcode license must be accepted in order to be connected…”

El problema

Tras actualizar XCode a una versión posterior y desde entonces al intentar conectar desde Windows utilizando Xamarin Mac Agent…

Oops!

El mensaje de error nos lo deja todo muy claro, debemos abrir XCode y aceptar la neuva licencia. Sin embargo, tras abrir XCode, nunca salta la ventana para poder aceptar la licencia.

¿Qué ocurre?, ¿qué podemos hacer?.

La solución

Encontramos una sencilla solución al poder aceptar la licencia de XCode utilizando la línea de comandos.

Abre XCode y dirígete a Preferences > Locations. Asegúrate de tener establecida a la última versión de XCode la opción Command Line Tools:

Command Line Tools

Todo preparado. Abre una línea de comandos y ejecuta:

sudo xcodebuild -license

Acepta la licencia (agree), vuelve a Visual Studio en Windows e intenta de nuevo establecer una conexión. Todo debería funcionar sin problemas.

Más información

[Tips and Tricks] Correción errores compilación Xamarin.Androd

AndroidIntroducción

Gracias a poder participar en múltiples talleres relacionados con el desarrollo Xamarin y principalmente, a los cursos Xamarin que tengo disponible en CampusMVP tengo la posibilidad de interactuar con una gran cantidad de desarrolladores que utilizan Xamarin. Esto me ha permitido conocer las principales dudas y los principales problemas a los que se enfrentan.

En el artículo de hoy, vamos a centrarnos en un error relacionado con la compilación Android dado en mayor medida tras actualizar el paquete de Xamarin.Forms o uno de los implicados con Xamarin.Android.

El problema

Tras actualizar el paquete de Xamarin.Forms o alguno de los implicados con Xamarin.Android obtenemos el siguiente error:

Please install package: 'Xamarin.Android.Support.v4' available in SDK installer. Java library file ...\AppData\Local\Xamarin\Xamarin.Android.Support.v4\23.3.0.0\content\libs/internal_impl-23.3.0.jar doesn't exist.	

También puede ser:

error APT0000: Error retrieving parent for item: No resource found that matches the given name 'Theme.AppCompat.Light.DarkActionBar'.

Xamarin descarga paquetes relacionados con el SDK de Android en la ruta %UserProfile%\AppData\Local\Xamarin\zips tras la restauración de paquetes. Dependiendo de varios factores como la conexión a internet, el tiempo de respuesta puede verse afectado. La implicación es el “congelado” del proceso de compilación en Visual Studio. Puedes creer que no esta sucediendo nada o bien, que algún error ha ocurrido. Ante esta situación, si se cancela la compilación o se cierra Visual Studio, todo puede quedar un estado indeterminado.

La solución

Lo primero que se suele intentar es limpiar y recompilar el proyecto. No funciona. Nos ponemos “más serios” y limpiamos la carpeta packages, bin y obj. Tampoco es suficiente.

Debemos de volver a permitir realizar la descarga de los paquetes relacionados con el SDK Android desde cero. Para ello:

  1. Cerrar Visual Studio.
  2. Acceder a la carpeta del proyecto, limpiar la carpeta packages.
  3. Limpiar todos los paquetes de Xamarin.Android disponibles en la cache de NuGet disponible en la ruta %UserProfile%\.nuget\packages\Xamarin.Android.*.
  4. Limpiar todos los paquetes de Xamarin.Android disponibles en la cache de Xamarin disponible en la ruta %UserProfile%\.nuget\packages\Xamarin.Android.*.
  5. ¿Recuerdas la ruta donde se descargaban los paquetes relacionados con el SDK de Android?. Limpiar las descargas no completadas de la ruta %UserProfile%\AppData\Local\Xamarin\zips.

Tras el proceso anterior, recompilar y esperar (es importante, paciencia!). Todo correcto de nuevo.

Más información

[Tips and Tricks] Corrección al error “Unsupported major.minor version 52.0”

androidEl error

Lleno de ilusión, descargas e instalas Xamarin y te dispones a crear tu primera aplicación móvil multiplataforma nativa con C#. Seleccionas el proyecto Android como proyecto de arranque, un simulador y compilas. Si tras breves segundos no ves tu aplicación en ejecución, quizás estas dentro del porcentaje reducido de desarrolladores que obtienen el siguiente error:

Unsupported major.minor version 52.0

Unsupported major.minor version 52.0

¿Qué ocurre?

Probablemente has instalado múltiples SDKs de Android utilizando Android SDK Manager. Xamarin Android intenta utilizar las últimas “Android Build-Tools” aún no compatibles.

La solución

Tenemos dos caminos posibles.

El primero de ellos se basa en actualizar Java JDK y asegurar su uso. La versión 52.0 referenciada en el error se refiere al JDK, en concreto a la versión 8. Xamarin Android 7.0 requiere el JDK 1.8 para usar las APIs de Android Nougat (API Level 24). Es necesaria además una versión de 64 bits para poder usar controles personales en el editor Android entre otras acciones.

Descargamos la versión correspondiente del JDK en este enlace.

Tras descargar e instalar, debemos asegurar que se utiliza la versión instalada. Para ello:

  • Visual Studio: Tools > Options > Xamarin > Android Settings > Java Development Kit Location.
  • Xamarin Studio (en Mac): Xamarin Studio > Preferences > Projects > SDK Locations > Android > Java SDK (JDK).

El segundo camino se basa en utilizar Android 6.0 o lo que es lo mismo el API Level 23. Abrimos Android SDK Manager:

Abrimos Android SDK Manager

Abrimos Android SDK Manager

Debemos desinstalar:

  • Android SDK Build-tools 24.0.x.

Y tener instalado:

  • Android SDK Build-tools 23.0.x.
  • SDK Platform 23.
Android SDK Manager

Android SDK Manager

Más información

[Tips and Tricks] Corregir error “could not connect to the debugger” utilizando Visual Studio Android Emulator

device-tablet-wfEl problema

Estas desarrollando una aplicación nativa multiplataforma con Xamarin con soporte a Android, te disponibles a lanzar y depurar la misma en el emulador Android incluido con Visual Studio y…

No se puede depurar!

No se puede depurar!

La aplicación realiza el despliegue e incluso arranca en el emulador, pero se detiene inmediatamente sin permitir depurar. Obtenemos el mensaje:

Could not connect to the debugger.

¿Cómo solucionamos el problema?

La solución

El error radica en incompatibilidades entre el procesador que hace de host y la máquina virtual Hyper-V.

En Windows 10, pulsamos el botón de inicio y escribimos MMC. A continuación, pulsamos la opción Hyper-V Manager:

Hyper-V Manager

Hyper-V Manager

En la herramienta de gestión de máquinas Hyper-V (emuladores) seleccionamos la que queremos usar y hacemos clic derecho, Settings.

Virtual Machines

Virtual Machines

En la ventana de configuración de la máquina, vamos a la sección Compatibility y habilitamos Migrate to a physical computer with a different processor version:

Configuración de compatibilidad

Configuración de compatibilidad

Si ejecutamos de nuevo la aplicación depurando desde Visual Studio, todo debe funcionar como se espera.

Más información

[Tips and Tricks] “Error MT0091: This version of Xamarin.iOS requires the iOS 10.0 SDK (shipped with Xcode 8.0) when the managed linker is disabled”

i-phoneEl problema

Desarrollando una aplicación con Xamarin para iOS, acabas de actualizar recientemente (Cycle 8) y al intentar compilar y desplegar el proyecto te encuentras con el siguiente error:

Error MT0091

Error MT0091

¿Qué ocurre?

La solución

El problema viene dado por tener la última versión de Xamarin.iOS ya preparada para iOS 10.0  y no tener XCode actualizado a la última versión. Xamarin.iOS 10 incluye los simbolos de XCode 8.

Tenemos dos soluciones.

  • La primera de ellas es sencilla, actualizar XCode a la versión 8.0.
  • La segunda opción es indicar al Linker que no utilice estos simbolos para permitir la compilación contra versiones anteriores de XCode (como es tu caso). Debes dirigirte a las propiedades del proyecto (clic derecho), pestaña Build, iOS Build y acceder a la opción Linker Behavior. Debes seleccionar la opción Link Framework SDKs only.

Más información

[Tips and Tricks] Windows 10. Adaptar recursos por DPI de pantalla

Scale to Fit-02Introducción

Con Windows 10 los desarrolladores recibimos la culminación de un gran viaje en la convergencia entre las diferentes plataformas Windows. Ahora podemos desarrollar aplicaciones para gran diversidad de familias de dispositivos como móviles, PCs, tabletas, IoT y otros que están por llegar, compartiendo la mayor cantidad de código, con un mismo proyecto y paquete. Además, contamos con grandes nuevas características como Continuum en teléfonos que permite convertirlo en un PC utilizando Microsoft Display Dock o Miracast.

Sin embargo, hay un detalle claro y obvio. Si contamos con un mismo paquete para todos esos dispositivos diferentes…¿cómo adaptamos la experiencia para ofrecer la mejor opción adaptada posible?

Debemos adaptar la interfaz de usuario en cada familia de plataforma para lograr ofrecer la mejor experiencia posible adaptada a la perfección. Para ello, utilizamos:

  • AdaptiveTriggers
  • Nuevos controles como RelativePanel y/o SplitView
  • Detección de modos de interacción
  • Etc

Sin embargo, hay elementos vitales en la mayoría de aplicaciones, que no acaban recibiendo la atención que se merecen. Estoy hablando de las imagenes. La aplicación puede usar una imagen que se visualiza perfectamente en un teléfono pero…¿y si se usa la aplicación con Continuum en una pantalla con una resolución diferente (más elevada)?.

En este artículo, vamos a aprender como organizar y utilizar los recursos de la aplicación para que se utilicen y adapten por DPI.

DisplayInformation

La clase DisplayInformation cuenta con propiedades y eventos que nos permiten verificar y monitorear información relacionada con la pantalla física. Para monitorear detalles como cambios en DPI o la rotación podemos usar la clase DisplayInformation.

En nuestra interfaz vamos a mostrar la siguiente información:

<StackPanel
     Orientation="Horizontal">
     <TextBlock Text="Logical DPI:" />
     <TextBlock Text="{Binding LogicalDpi}" />
     <TextBlock Text="DPI" />
</StackPanel>

<StackPanel
     Orientation="Horizontal">
     <TextBlock Text="Scaling:" />
     <TextBlock Text="{Binding Scale}" />
     <TextBlock Text="%" />
</StackPanel>

De modo que, en la viewmodel bindeada definiremos dos propiedades:

private string _logicalDpi;
public string LogicalDpi
{
     get { return _logicalDpi; }
     set
     {
          _logicalDpi = value;
          RaisePropertyChanged();
     }
}

private string _scale;
public string Scale
{
     get { return _scale; }
     set
     {
          _scale = value;
          RaisePropertyChanged();
     }
}

Una para cada valor que deseamos mostrar en pantalla. Utilizaremos el método DpiChanged lanzado cada vez que la propiedad LogicalDpi se modifica, cuando cambian los píxeles por pulgada (PPI) de la pantalla.

private DisplayInformation _displayInformation;

_displayInformation = DisplayInformation.GetForCurrentView();

Tras obtener la información física actual de la pantalla utilizando el método GetForCurrentView nos suscribimos al evento DpiChanged:

_displayInformation.DpiChanged += _displayInformation_DpiChanged;

Cada vez que el evento se lanza, actualizamos la información mostrada en pantalla:

private void _displayInformation_DpiChanged(DisplayInformation sender, object args)
{
     DisplayInformation displayInformation = sender as DisplayInformation;

     UpdateDpi(displayInformation);
}

private void UpdateDpi(DisplayInformation displayInformation)
{
     if (displayInformation != null)
     {
          LogicalDpi = displayInformation.LogicalDpi.ToString();
          Scale = (displayInformation.RawPixelsPerViewPixel * 100.0).ToString();
     }
}

Mostramos los píxeles por pulgada lógica de la pantalla actual utilizando la propiedad LogicalDpi, mientras que para la escala utilizamos la propiedad RawPixelsPerViewPixel que indica el número de píxeles físicos (RAW) por cada  pixel mostrado (Layout). Para obtener la escala bastará con multiplicar el valor por cien.

NOTA: En este ejemplo utilizamos la clase DisplayInformation para mostrar información contextual relacionada con el escalado de imágenes utilizado. Sin embargo, utilizando propiedades como DiagonalSizeInInches podemos saber facilmente el tamaño en pulgadas de la pantalla y así adaptar la interfaz en consecuencia. Sumamente útil y sencillo combinado con el uso de AdaptiveTriggers personalizados.

Recursos por DPI

Para optimizar nuestra interfaz en cada posible dispositivo o condición, podemos facilitar diferentes assets para diferentes resoluciones y escalas. Cada dispositivo cuenta con una escala específica resultante de la densidad de píxeles física y la distancia de visión teórica.

La escala es utilizada por el sistema, que realiza una gestión de recursos para determinar que recurso es el más adecuado entre las opciones facilitadas por los desarrolladores en sus aplicaciones.

NOTA: Los teléfonos suelen tener una escala de entre 200 y 400 mientras que dispositivos conectados como monitores y TVs tiene valores de 100 y 150 respectivamente.

Ejemplos de escala

Ejemplos de escala

Añadiendo recursos por escala

Para soportar el uso de diferentes recursos dependientes de la escala, bastará con añadirlos de la forma adecuada. Contamos con dos formas diferentes para ello.

Por un lado, podemos sencillamente añadir el mismo recurso con diferentes tamaños utilizando la notación .scale-xxx dentro de la carpeta Assets:

Recursos por DPI

Recursos por DPI

Por otro lado, podemos añadir diferentes carpetas con el nombre de la escala, es decir, scale-xxx incluyendo como contenido los recursos.

Utilizando recursos por escala

En nuestra carpeta de Assets contamos con una imágen única llamada Picture-NoScale:

<Image
     Source="ms-appx:///Assets/Picture-NoScale.png"
     Height="100"
     Width="100"
     HorizontalAlignment="Left"/>

Con el código anterior, usaremos la misma (y única) imágen existente bajo cualquier condición. Si la escala es alta y requiere de recursos con mayor resolución, el resultado será una visualización borrosa de la misma. Proporcionamos una experiencia no idónea.

Contamos con múltiples opciones por escala del  recurso llamado Picture, bastará con utilizarlo ignorando scale-xxx de la ruta:

<Image
    Source="ms-appx:///Assets/Picture.png"
    Height="100"
    Width="100"
    HorizontalAlignment="Left"/>

Utilizando los recursos vistos previamente, donde en un caso usamos una imágen única bajo cualquier condición y en otro una adapada a diferentes escalas, el resultado es el siguiente:

Carga de Assets por DPI

Carga de Assets por DPI

Tenemos 192DPI con una escala de 200%. Podemos ver a simple vista que mientras que la primera imágen se visualiza pixelada, la segunda se aprecia con una calidad alta.

Sencillo, ¿cierto?

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

[Tips and Tricks] DeviceFamily Adaptive XAML Tool

WindowsIntroducción

Con la llegada del SDK de Windows 10 Preview tenemos la posibilidad de crear Apps Universales con un único binario que funcione en múltiples plataformas. Es un paso importante pero que conlleva realizar una acción que sera comun, diferenciar entre las diferentes plataformas donde correrá dicho binario para poder adaptar la interfaz de usuario. Con ese objetivo utilizamos entre otras opciones los Adaptive Triggers de los que ya hemos hablado.

Sin embargo, en ocasiones la misma vista en diferentes dispositivos puede que sea totalmente diferente.

En estos casos podemos crear vistas diferentes por familias de dispositivos. Tras añadir una vista de la forma habitual, creamos una carpeta siguiente la siguiente nomenclatura:

  • DeviceFamily-[Family]

Donde Family es la familia del dispotivo para el que deseamos sobrescribir la vista.Dentro de esta carpeta añadimos la vista XAML deseada en esa plataforma.

NOTA: Añadimos la sobreescritura de la vista. Es importante un detalle del fichero añadido, no añadimos code behind. Esta vista utilizará el mismo code behind que la que teníamos previamente.

DeviceFamily Adaptive XAML Tool

Gestionar carpetas o vistas por familia de dispositivo se vuelve aun más sencillo gracias a la extensión Device Family Adaptive XAML Tool creada por Olivier Matis.

Podemos hacer clic derecho sobre la solución para acceder a un menu contextual llamado “Add single folder” para añadir carpeta de vistas específica para una plataforma concreta. Además, haciendo clic sobre una vista existente tendremos acceso a otro menu contextual “Add device family XAML” que nos creará la vista XAML específica para la familia de dispositivos seleccionada.

DeviceFamily Adaptive XAML Tool

DeviceFamily Adaptive XAML Tool

Sencillo pero extremadamente útil, ¿cierto?.

Más información

[Tips and Tricks] Diccionario de recursos por plataforma en Windows 10

Application-01Introducción

Con la llegada del SDK de Windows 10 Preview tenemos la posibilidad de crear Apps Universales con un único binario que funcione en múltiples plataformas. Es un paso importante pero que conlleva realizar una acción que sera comun, diferenciar entre las diferentes plataformas donde correrá dicho binario para poder adaptar la interfaz de usuario. Con ese objetivo utilizamos entre otras opciones los Adaptive Triggers de los que ya hemos hablado.

Sin embargo, en ocasiones la misma vista en diferentes dispositivos puede que sea totalmente diferente.

En estos casos podemos crear vistas diferentes por familias de dispositivos. Tras añadir una vista de la forma habitual, creamos una carpeta siguiente la siguiente nomenclatura:

  • DeviceFamily-[Family]

Donde Family es la familia del dispotivo para el que deseamos sobrescribir la vista.Dentro de esta carpeta añadimos la vista XAML deseada en esa plataforma.

NOTA: Añadimos la sobreescritura de la vista. Es importante un detalle del fichero añadido, no añadimos code behind. Esta vista utilizará el mismo code behind que la que teníamos previamente.

Lo visto hasta ahora es genial para poder crear con facilidad vistas diferentes, pero…¿y a nivel de recursos y estilos?

Utilizando diccionarios de recursos por plataforma de dispositivos

En diccionarios de recursos, archivos XAML, organizamos los recursos y estilos utilizados por la aplicación. Si deseamos recursos o estilos diferentes por plataformas podemos crear diferentes elementos con etiquetas distintas de modo que utilicemos en cada plataforma uno diferente (utilizando Adaptive Triggers por ejemplo). El problema de la situación anterior es que en la mayoría de casos, los cambios son mínimos y pasamos a agrandar el conjunto de recursos dificultando el mantenimiento de la aplicación.

¿Podemos mejorar esta situación?

Si. Podemos crear diccionarios de recursos compartidos con todo el conjunto de recursos comunes junto a diccionarios de recursos específicos por plataforma con estilos concretos a utilizar en las mismas.

¿Cómo sería?

Vamos a crear un ejemplo simple donde tendremos un rectángulo enlazado a un color. Utilizaremos un color definido en un diccionario de recursos genérico usado en todas las plataformas. Sin embargo, en teléfonos modificaremos el color añadiendo un diccionario de recursos específico para teléfonos donde sobreescribiremos el color.

Comenzamos. Añadimos un diccionario de recursos llamado Colors:

<Color x:Key="AccentColor">DeepSkyBlue</Color>
<SolidColorBrush x:Key="AccentBrush" Color="{StaticResource AccentColor}" />

Definimos el color a utilizar y registramos el diccionario en los recursos de la aplicación:

<Application.Resources>
     <ResourceDictionary>
          <ResourceDictionary.MergedDictionaries>
               <ResourceDictionary Source="Resources/Colors.xaml" />
          </ResourceDictionary.MergedDictionaries>
     </ResourceDictionary>
</Application.Resources>

En nuestra interfaz contaremos con un rectángulo relleno con el color definido.

<Rectangle
     Height="200"
     Width="250"
     Fill="{StaticResource AccentBrush}"/>

Hasta aquí, si ejecutamos la aplicación en cualquiera de las plataformas soportadas, el rectángulo se vera azul cielo.

A continuación, vamos a sobreescribir el color del rectángulo en teléfonos. Creamos un nuevo diccionario de recursos de igual nombre pero añadiendo al nombre .DeviceFamily-[Family] donde Family es la familia del dispotivo para el que deseamos sobrescribir el recurso. En nuestro ejemplo se llamará Colors.DeviceFamily-Mobile.xaml:

<Color x:Key="AccentColor">Red</Color>
<SolidColorBrush x:Key="AccentBrush" Color="{StaticResource AccentColor}" />

Definimos un nuevo color. Si ejecutamos la aplicación en Windows:

Color tomado del recurso por defecto

Color tomado del recurso por defecto

Mientras que en un teléfono:

Color tomado del recurso específico para teléfonos

Color tomado del recurso específico para teléfonos

Sencillo pero versátil, ¿cierto?.

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

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

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

Más información

 

[Windows 10] Utilizando x:Bind en un diccionario de recursos

Link - 05Introducción

Data binding es un mecanismo mediante el cual podemos enlazar los elementos de la interfaz de usuario con los objetos que contienen la información a mostrar. Cuando realizamos data binding, creamos una dependencia entre el valor de una propiedad llamada target con el valor de otra propiedad llamada source. Donde normalmente, la propiedad target recibirá el valor de la propiedad source.

Es el mecanismo base que nos permite utilizar el patrón MVVM en nuestras Apps móviles logrando:

  • 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.

Sin embargo, además de toda la potencia mencionada teníamos ciertas limitaciones. Los errores de Binding no se producían en tiempo de compilación de la App además de tener diferentes mejoras relacionadas con el rendimiento. Limitaciones existentes hasta ahora…

Con la llegada de Windows 10 tenemos la posibilidad de crear bindings compilados en lugar de los bindings clásicos.

x:Bind

x:Bind es una nueva síntaxis en XAML que cubre un objetivo similar a Binding. Permite crear un enlace a datos pero con significativas diferencias. Mientras que con Binding se utiliza reflexión en tiempo de ejecución para resolver el enlace a datos, con x:Bind se realiza una validación en tiempo de ejecución ya que son fuertemente tipados y compilados. Además, ofrece potentes mejoras en el rendimiento.

Crearemos un nuevo proyecto UAP:

Nueva App UAP

Nueva App 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.

En esta ocasión, nuestro objetivo sera crear un listado de casas donde utilizaremos x:Bind en la plantilla que representará cada elemento de la lista.

Comenzamos creando la entidad casa dentro de la carpeta Models:

public class House
{
     public string Place { get; set; }
     public string Price { get; set; }
     public string Photo { get; set; }
}

Nuestra interfaz sera muy simple en esta ocasión contando con un sencillo ListView:

<ListView
     ItemsSource="{Binding Houses}" />

El control tiene la fuente de datos enlazada a una propiedad de la ViewModel:

private ObservableCollection<House> _houses; 
 
public ObservableCollection<House> Houses
{
     get
     {
          if (_houses == null)
               LoadHouses();
 
          return _houses;
     }
} 

Cargaremos el listado de casas con un método creando datos falsos en local de manera aleatoria:

private void LoadHouses()
{
     _houses = new ObservableCollection<House>();
     Random random = new Random();
     for (int i = 0; i < 100; i++)
     {
          _houses.Add(new House
          {
               Place = Places[random.Next(0, Places.Count)],
               Photo = string.Format("ms-appx:///Assets/{0}.png", random.Next(1, 4)),
               Price = string.Format("${0}", random.Next(10000, 100000).ToString())
          });
     }
}

Y llegamos a la parte más importante, la definición del template de cada casa, en un diccionario de recursos. Creamos el diccionario de recursos:

Creamos diccionario de recursos

Creamos diccionario de recursos

Lo registramos en los recursos de la App:

<ResourceDictionary.MergedDictionaries>
     <ResourceDictionary Source="/Styles/AppResourceDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>  

Definimos el template:

<DataTemplate x:Key="HouseTemplate" x:DataType="model:House">
     <Grid Width="200"
           Height="80">
          <Grid.ColumnDefinitions>
               <ColumnDefinition Width="75" />
               <ColumnDefinition Width="*" />
          </Grid.ColumnDefinitions>
          <Grid.RowDefinitions>
               <RowDefinition Height="Auto" />
               <RowDefinition Height="Auto" />
           </Grid.RowDefinitions>
           <Image Grid.RowSpan="2"
              Source="{x:Bind Photo}"
              MaxWidth="70"
              MaxHeight="70" />
           <TextBlock Text="{x:Bind Place}"    
                  Grid.Column="1"
                  FontSize="18"/>
           <TextBlock Text="{x:Bind Price}"  
                  Grid.Column="1"  
                  Grid.Row="1"
                  FontSize="12" />
     </Grid>
</DataTemplate>

Utilizamos x:Bind para enlazar cada elemento visual de la plantilla a la propiedad deseada. Importante resaltar además de compilados, son fuertemente tipados. Es obligatorio para no tener errores de compilación indicar el tipo de los datos a los que accedemos por enlace a datos. Esto lo realizamos utilizando x:DataType. En nuestro ejemplo, la entidad House.

Nuestro ListView quedara:

<ListView
     ItemsSource="{Binding Houses}"
     ItemTemplate="{StaticResource HouseTemplate}" />

Ejecutamos la App y…

Error de compilación

Error de compilación

Diccionario de recursos, el problema

x:Bind o bindings compilados, como indicamos en el nombre deben ser precompilados. No podemos añadir recursos haciendo uso de bindings compilados ya sea a nivel de página o de Aplicación directamente; debemos inicializar e instanciar una clase.

La solución

Debemos añadir una clase parcial, código asociado al recurso para poder realizar la instanciación del mismo. Creamos la clase parcial:

public partial class AppResourceDictionary
{
     public AppResourceDictionary()
     {
         InitializeComponent();
     }
}

Asociamos la clase parcial con nuestro diccionario de recursos:

x:Class="XBindResources.Resources.AppResourceDictionary"

Modificamos el diccionario de recursos añadiendo la etiqueta x:Class. A continuación, instanciamos el diccionario de recursos:

<ResourceDictionary.MergedDictionaries>
                
     <!-- Resources -->
     <resources:AppResourceDictionary />      
                
</ResourceDictionary.MergedDictionaries>

Nos aseguramos que se lanza la llamada a InitializeComponent del mismo.

Si ejecutamos ahora nuestra App:

DataTemplate utilizando x:Bind y x:Phase

DataTemplate utilizando x:Bind y x:Phase

Voila!

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