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:
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:
1 2 3 4 5 6 |
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:
1 2 |
<ListView ItemsSource="{Binding Houses}" /> |
El control tiene la fuente de datos enlazada a una propiedad de la ViewModel:
1 2 3 4 5 6 7 8 9 10 11 12 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
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:
Lo registramos en los recursos de la App:
1 2 3 |
<ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="/Styles/AppResourceDictionary.xaml" /> </ResourceDictionary.MergedDictionaries> |
Definimos el template:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<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:
1 2 3 |
<ListView ItemsSource="{Binding Houses}" ItemTemplate="{StaticResource HouseTemplate}" /> |
Ejecutamos la App y…
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:
1 2 3 4 5 6 7 |
public partial class AppResourceDictionary { public AppResourceDictionary() { InitializeComponent(); } } |
Asociamos la clase parcial con nuestro diccionario de recursos:
1 |
x:Class="XBindResources.Resources.AppResourceDictionary" |
Modificamos el diccionario de recursos añadiendo la etiqueta x:Class. A continuación, instanciamos el diccionario de recursos:
1 2 3 4 5 6 |
<ResourceDictionary.MergedDictionaries> <!-- Resources --> <resources:AppResourceDictionary /> </ResourceDictionary.MergedDictionaries> |
Nos aseguramos que se lanza la llamada a InitializeComponent del mismo.
Si ejecutamos ahora nuestra App:
Voila!
Podéis encontrar el ejemplo realizado en GitHub.
Más información
- Channel 9: Data Binding: Boost Your Apps’ Performance Through New Enhancements to XAML Data Binding
- Visual Studio Magazine: Compiled Data Binding in the Universal Windows Platform
Deja un comentario