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

Introducció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:

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

Deja un comentario

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