Usando Tap Gestures en Images dentro de un  ListView

Hoy aprenderemos a hacer clic en una imagen dentro de un listView con tap gestures en xamarin y c#.

Todo programador sabe que a veces nos pasamos más tiempo peleándonos con librerías, errores del Ide y errores que desconocemos, buscando una solución por internet.

Mi último caso fue cómo crear un CarouselView en Xamarin para una presentación, algo muy sencillo pero que por un fallo básico no lograba hacer que funcionara correctamente.

En mi caso personal necesitaba solucionar lo del tap gesture, y he tardado bastantes horas en arreglarlo, foros en inglés con casos muy particulares que no me aportaban mucho más que una ligera idea, pero no una solución.

Aún así no había logrado avanzar, hasta hoy que por fin he dado con la solución y quería compartirla con todos vosotros para optimizar vuestro tiempo, pero primero expliquemos el problema.

GestureRecognizers no funciona en un listView

Cuando tenemos una lista de tareas y usamos un listView podemos hacer clic en un item y accederemos al registro seleccionado gracias a la propiedad ItemSelected del listView.

Hasta ahí todo bien, cuando seleccionamos uno de ellos podemos hacer que se vaya a un método para eliminar o editar pero, ¿ que pasa si lo que deseamos es hacer clic, en una imagen dentro de la celda ?.

Pues lo que pasa es que no funciona porque la app entiende que no has hecho clic en la celda para seleccionar su item, lo que entiende es que has hecho clic en una simple imagen y se olvida que estás en una lista, por lo que nunca sabrás que item es y no podrás ni borrarlo ni editarlo, la lista estará a null ( vacía) .

Tenemos un ListView con Tap Gestures

Vamos con una solución para hacer Tap o Clic en la imagen del listView.

Vamos a partir de la idea que ya tenemos un ListView en nuestro código XAML.

Junto a la tarea deseamos meter una imagen para borrar la tarea o editarla.

Un código sencillo para conseguir esto podría ser algo como esto

<ListView x:Name="lista"
              Margin="{StaticResource PageMargin}"
              ItemSelected="OnListViewItemSelected"             
              Background="#184060">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout x:Name="rowColor" BackgroundColor="{Binding ColorActived}"
                        Orientation="Vertical">
                            <StackLayout Orientation="Horizontal" >
                                <Label Text="{Binding Text}"
                                       TextColor="{Binding ColorTextLabel}"                                       
                                       VerticalOptions="Center"                                       
                                       Margin="6,0,0,0"
                                       FontSize="18"/>                           
                                <Image Source="edit"
                                       HeightRequest="32"
                                       HorizontalOptions="EndAndExpand"
                                       Margin="0,0,10,0">
                                <Image.GestureRecognizers>                                    
                                    <TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped_Edit"/>
                                </Image.GestureRecognizers>
                            </Image>

Cómo podéis apreciar tenemos un Label donde mostramos el texto por cada registro y una imagen que es la que nos interesa hacer clic y nos haga algo.

Hasta este punto tenemos lo que comentamos antes, podemos hacer TAP a la imagen y nos llevará a un método llamado TapGestureRecognizer_Tapped_Edit pero no sabremos que registro de la lista hemos seleccionado.

Para solucionar esto nos vamos a nuestro ViewModel lo llamaremos VMTareas y creamos un Comando. tal que así:

public ICommand ListaSelected => new Command<Note>(async (p) => await Msn(p));

El comando lo he llamado ListaSelected y le decimos que me cree un nuevo comando con la clase Note y que llame a un método asíncrono llamado por ejemplo MSN ( este método solo va a mostrar un mensaje con el nombre de la tarea).

Recordar que para usar métodos asíncronos tenéis que agregar using System.Threading.Tasks; y para usar ICommand agregar using System.Windows.Input;

Ahora escribir en VMTareas el método asíncrono por ejemplo algo como esto

public async Task Msn(Note note)
        {
            await App.Current.MainPage.DisplayAlert("Alerta",note.Text,"fsg");
        }

Lo que voy a mostrar es el nombre de mi clase Note donde tengo los campos que voy a mostrar.

Tenemos un Modelo Note

Podéis tener un modelo donde trabajar nuestras tareas, en mi caso lo he llamado Note y he agregado los campos así

public class Note
    {
        //establecer en el modelo los campos de la base de datos.
        [PrimaryKey, AutoIncrement]
        public int ID { get; set; }
        public string Text { get; set; }
   }

No necesitáis tener una base de datos como yo, podéis tener vuestros datos en una colección o array, pero lo dejo por si es vuestro caso.

Modificamos el C# de nuestra vista

Para acabar la modificación para prepararlo todo solo tenéis que iros al código C# de nuestra vista Xaml y decirle que vuestro VMtareas va a ser un BindigContext.

public NotesPage(){
          InitializeComponent();
          BindingContext = new VMtareas();
}

Ya tenéis todo listo ahora vamos a la parte importante, llamar al comando.

Usar Command para Tap Gesture en un ListView

Recordar que antes teniamos:

                                <Image Source="edit"
                                       HeightRequest="32"
                                       HorizontalOptions="EndAndExpand"
                                       Margin="0,0,10,0"
                                       IsVisible="{Binding VisibleIconEdit}">
                                <Image.GestureRecognizers>                                    
                                    <TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped_Edit"/>
                                </Image.GestureRecognizers>
                            </Image>

Por lo tanto, lo sustituimos por:

                                 <Image Source="edit"
                                       HeightRequest="32"
                                       HorizontalOptions="EndAndExpand"
                                       Margin="0,0,10,0"
                                       IsVisible="{Binding VisibleIconEdit}">
                                 <Image.GestureRecognizers>
                                    <TapGestureRecognizer Command="{Binding Path=BindingContext.ListaSelected, Source={x:Reference lista}}"
                                                          CommandParameter="{Binding .}"/>
                                </Image.GestureRecognizers>
                            </Image>

Hemos cambiado el Tapped=»TapGestureRecognizer_Tapped_Edit» por un command llamado ListaSelected en nuestro VMtareas y el Source es como hemos llamado a nuestro listView en mi caso lo llamé x:Name=»lista»

Pero con esta línea no es suficiente, necesitamos pasarle como parámetro todo el Binding completo, para ello lo hacemos con CommandParameter=»{Binding .}»

Como podéis ver en la imagen, haciendo clic o tap en la imagen de la primera tarea nos lleva al método con los datos que hemos seleccionados, ahora ya podéis borrar, editar o hacer lo que necesitéis.

Espero que os haya servido de ayuda

 
Resumen
Usando Tap Gestures en Images dentro de un  ListView
Nombre del artículo
Usando Tap Gestures en Images dentro de un  ListView
Descripción
Hoy aprenderemos a hacer clic en una imagen dentro de un listView con tap gestures en xamarin y c#.
Autor
Publicador
lenguajesdeprogramacion.com
Logo

Deja un comentario