[Xamarin.Forms] RelativeSource Binding

Introducción

Estas usando un control enlazado a una colección (por ejemplo, un listado de peliculas) y en cada elemento cuentas con un botón para añadir la pelicula a favoritos. Por defecto, cada elemento tendra como contexto la pelicula de la colección enlazada al listado y añadir un comando en cada elemento no suena como la mejor idea pero…¿que hacemos en este caso?.

RelativeSource

Contábamos ya con otras soluciones para hacer Binding a un elemento visual (x:Reference) pero nos llega RelativeSource, la solución ideal en casos como el anterior.

RelativeSource es una extensión de marcado que se utiliza en casos de enlace particulares cuando intentamos vincular una propiedad de un objeto a otro de sus padres relativos. 

Veamoslo con un ejemplo sencillo. Vamos a trabajar con tareas:

public class TodoItem
{
     public string Name { get; set; }
     public string Description { get; set; }
     public bool IsDone { get; set; }
}

De modo que en la ViewModel contaremos con un listado de tareas:

Items = new ObservableCollection<TodoItem>
{
     new TodoItem
     {
          Name = "Create RelativeSource Demo"
     },
     new TodoItem
     {
          Name = "Buy Milk"
     },
     new TodoItem
     {
          Name = "Go for a walk"
     }
};

Y un comando:

public ICommand DeleteTodoItemCommand => new Command<TodoItem>(DeleteTodoItem);

NOTA: Fíjate que cada TodoItem no cuenta con un comando.

En la interfaz de usuario:

<ListView 
     ItemsSource="{Binding Items}">
     <ListView.ItemTemplate>
          <DataTemplate>
               <ViewCell>
                    <Grid>
                         <Grid.ColumnDefinitions>
                              <ColumnDefinition Width="*" />
                              <ColumnDefinition Width="80" />
                         </Grid.ColumnDefinitions>
                         <Label 
                              Grid.Column="0"
                              Text="{Binding Name}"/>
                         <Button 
                              Grid.Column="1"
                              Text="Delete" 
                              CommandParameter="{Binding}" 
                              Command="{Binding Source={RelativeSource AncestorType={x:Type viewModels:MainViewModel}}, Path=DeleteTodoItemCommand}"/>
                    </Grid>
               </ViewCell>
          </DataTemplate>
     </ListView.ItemTemplate>
</ListView>

El resultado:

Usando RelativeSource

El comando hace uso de RelativeSource para acceder al ancestro de tipo MainViewModel y Path, el comando.

Puedes encontrar el código del ejemplo en GitHub:

Ver GitHubOtra extensión de marcada añadida que viene a solucionar ciertos casos. ¿Qué te parece el añadido?.

Recuerda, cualquier comentario o feedback es bienvenido en los comentarios de la entrada.

Más información

2 pensamientos en “[Xamarin.Forms] RelativeSource Binding

Deja un comentario