Compartir vía


Interactividad de ListView

La clase Xamarin.FormsListView admite la interacción del usuario con los datos que presenta.

Selección y pulsaciones

El modo de selección ListView se controla estableciendo la propiedad ListView.SelectionMode en un valor de la enumeración ListViewSelectionMode:

  • Single indica que se puede seleccionar un solo elemento, con el elemento seleccionado resaltado. Este es el valor predeterminado.
  • None indica que no se puede seleccionar ningún elemento.

Cuando un usuario pulsa un elemento, se desencadenan dos eventos:

  • ItemSelected se activa cuando se selecciona un nuevo elemento.
  • ItemTapped se activa cuando se pulsa un elemento.

Al pulsar el mismo elemento dos veces se activarán dos eventos de ItemTapped, pero solo se activará un solo evento ItemSelected.

Nota:

La clase ItemTappedEventArgs, que contiene los argumentos del evento ItemTapped, tiene propiedades Group y Item, y una propiedad ItemIndex cuyo valor representa el índice en la ListView del elemento pulsado. Del mismo modo, la clase SelectedItemChangedEventArgs, que contiene los argumentos del evento ItemSelected, tiene una propiedad SelectedItem, y una propiedad SelectedItemIndex cuyo valor representa el índice en la ListView del elemento seleccionado.

Cuando la propiedad SelectionMode se establece en Single, los elementos de la ListView se pueden seleccionar, los eventos ItemSelected y ItemTapped se activarán, y la propiedad SelectedItem se establecerá en el valor del elemento seleccionado.

Cuando la propiedad SelectionMode se fija en None, los elementos de la ListView no podrán seleccionarse, el evento ItemSelected no se activará y la propiedad SelectedItem permanecerá null. Sin embargo, los eventos ItemTapped seguirán activándose y el elemento sobre el que se haya pulsado aparecerá brevemente resaltado durante la pulsación.

Cuando se haya seleccionado un elemento y la propiedad SelectionMode se cambie de Single a None, la propiedad SelectedItem se fijará en null y el evento ItemSelected se activará con un elemento null.

Las capturas de pantalla siguientes muestran un elemento ListView con el modo de selección predeterminado:

ListView con Selección habilitada

Deshabilitar selección

Para deshabilitar la selección ListView ajuste la propiedad SelectionMode a None:

<ListView ... SelectionMode="None" />
var listView = new ListView { ... SelectionMode = ListViewSelectionMode.None };

acciones de contexto

A menudo, los usuarios querrán realizar una acción en un ListView. Por ejemplo, considere una lista de correos electrónicos en la aplicación Mail. En iOS, puede deslizar el dedo para eliminar un mensaje:

ListView con acciones de contexto

Las acciones contextuales pueden implementarse en C# y XAML. A continuación encontrará guías específicas para ambos, pero antes echemos un vistazo a algunos detalles clave de la aplicación de ambos.

Las Acciones de Contexto se crean utilizando elementos MenuItem. Los eventos de pulsación de los objetos MenuItems los genera el propio MenuItem, no el ListView. Esto es diferente de cómo se gestionan los eventos de pulsación para las celdas, donde el ListView genera el evento en lugar de la celda. Dado que genera el evento ListView, su controlador de eventos recibe información clave, como el elemento seleccionado o pulsado.

De forma predeterminada, un MenuItem no tiene forma de saber a qué celda pertenece. La propiedad CommandParameter está disponible en MenuItem para almacenar objetos, como el objeto detrás del MenuItem de ViewCell. La propiedad CommandParameter se puede establecer tanto en XAML como en C#.

XAML

Los elementos MenuItem se pueden crear en una colección XAML. En el código XAML siguiente se muestra una celda personalizada con dos acciones de contexto implementadas:

<ListView x:Name="ContextDemoList">
  <ListView.ItemTemplate>
    <DataTemplate>
      <ViewCell>
         <ViewCell.ContextActions>
            <MenuItem Clicked="OnMore"
                      CommandParameter="{Binding .}"
                      Text="More" />
            <MenuItem Clicked="OnDelete"
                      CommandParameter="{Binding .}"
                      Text="Delete" IsDestructive="True" />
         </ViewCell.ContextActions>
         <StackLayout Padding="15,0">
              <Label Text="{Binding title}" />
         </StackLayout>
      </ViewCell>
    </DataTemplate>
  </ListView.ItemTemplate>
</ListView>

En el archivo de código subyacente, asegúrese de que los métodos Clicked se implementan:

public void OnMore (object sender, EventArgs e)
{
    var mi = ((MenuItem)sender);
    DisplayAlert("More Context Action", mi.CommandParameter + " more context action", "OK");
}

public void OnDelete (object sender, EventArgs e)
{
    var mi = ((MenuItem)sender);
    DisplayAlert("Delete Context Action", mi.CommandParameter + " delete context action", "OK");
}

Nota:

El NavigationPageRenderer para Android tiene un método UpdateMenuItemIcon reemplazable que se puede usar para cargar iconos desde un Drawable personalizado. Esta invalidación permite usar imágenes SVG como iconos en instancias de MenuItem en Android.

Código

Las acciones de contexto se pueden implementar en cualquier subclase Cell (siempre que no se use como encabezado de grupo) creando instancias MenuItem y agregándolas a la colección ContextActions para la celda. Puede configurar las siguientes propiedades para la acción de contexto:

  • Texto: la cadena que aparece en el elemento de menú.
  • Hacer clic: el evento cuando se haga clic en el elemento.
  • IsDestructive: (opcional) cuando es true el elemento se representa de forma diferente en iOS.

Se pueden agregar varias acciones de contexto a una celda, pero solo debe haber una IsDestructive establecida en true. En el código siguiente se muestra cómo se agregarían las acciones de contexto a un ViewCell:

var moreAction = new MenuItem { Text = "More" };
moreAction.SetBinding (MenuItem.CommandParameterProperty, new Binding ("."));
moreAction.Clicked += async (sender, e) =>
{
    var mi = ((MenuItem)sender);
    Debug.WriteLine("More Context Action clicked: " + mi.CommandParameter);
};

var deleteAction = new MenuItem { Text = "Delete", IsDestructive = true }; // red background
deleteAction.SetBinding (MenuItem.CommandParameterProperty, new Binding ("."));
deleteAction.Clicked += async (sender, e) =>
{
    var mi = ((MenuItem)sender);
    Debug.WriteLine("Delete Context Action clicked: " + mi.CommandParameter);
};
// add to the ViewCell's ContextActions property
ContextActions.Add (moreAction);
ContextActions.Add (deleteAction);

Deslizar para actualizar

Los usuarios esperan que la extracción en una lista de datos actualice esa lista. El control ListView admite esta lista de fábrica. Para habilitar la funcionalidad de extracción a actualización, establezca IsPullToRefreshEnabled en true:

<ListView ...
          IsPullToRefreshEnabled="true" />

El código de C# equivalente es el siguiente:

listView.IsPullToRefreshEnabled = true;

Aparece un spinner durante la actualización, que es negro de forma predeterminada. Sin embargo, el color de número se puede cambiar en iOS y Android estableciendo la propiedad RefreshControlColor en un Color:

<ListView ...
          IsPullToRefreshEnabled="true"
          RefreshControlColor="Red" />

El código de C# equivalente es el siguiente:

listView.RefreshControlColor = Color.Red;

Las capturas de pantalla siguientes muestran la extracción para actualizar a medida que el usuario extrae:

Extracción de ListView para actualizar en curso

Las capturas de pantalla siguientes muestran la extracción para actualizar después de que el usuario haya liberado la extracción, con el spinner que se muestra mientras se actualiza el ListView:

Extracción de ListView para actualizar completada

ListView desencadena el evento Refreshing para iniciar la actualización y la propiedad IsRefreshing se establecerá en true. Cualquier código necesario para actualizar el contenido del ListView debe ejecutarse después por el controlador de eventos para el evento Refreshing o por el método ejecutado por el RefreshCommand. Una vez actualizado el ListView, la propiedad IsRefreshing debe establecerse en false, o se debe llamar al método EndRefresh para indicar que la actualización está completa.

Nota:

Al definir un RefreshCommand, se puede especificar el método CanExecute del comando para habilitar o deshabilitar el comando.

Detectar desplazamiento

ListView define un evento de Scrolled desencadenado para indicar que se produjo el desplazamiento. En el ejemplo de XAML siguiente se muestra ListView, que establece un controlador para el evento Scrolled:

<ListView Scrolled="OnListViewScrolled">
    ...
</ListView>

El código de C# equivalente es el siguiente:

ListView listView = new ListView();
listView.Scrolled += OnListViewScrolled;

En este ejemplo de código, el controlador de eventos OnListViewScrolled se ejecuta cuando se desencadena el evento Scrolled:

void OnListViewScrolled(object sender, ScrolledEventArgs e)
{
    Debug.WriteLine("ScrollX: " + e.ScrollX);
    Debug.WriteLine("ScrollY: " + e.ScrollY);  
}

El controlador de eventos OnListViewScrolled genera los valores del objeto ScrolledEventArgs que acompaña al evento.