Rellenar una CollectionView con datos
La interfaz de usuario de aplicación multiplataforma de .NET (.NET MAUI) CollectionView incluye las siguientes propiedades que definen los datos que se van a mostrar y su apariencia:
ItemsSource
, de tipoIEnumerable
, especifica la colección de elementos que se mostrarán en el área de sugerencias, y tiene un valor predeterminado denull
.ItemTemplate
, de tipo DataTemplate, especifica la plantilla que se aplicará a cada elemento de la colección de elementos que se mostrará.
Todas estas propiedades están respaldadas por objetos BindableProperty, lo que significa que las propiedades pueden ser destinos de los enlaces de datos.
CollectionView define una propiedad ItemsUpdatingScrollMode
que representa el comportamiento de desplazamiento de CollectionView cuando se agregan nuevos elementos. Para obtener más información sobre esta propiedad, consulta Control de la posición de desplazamiento cuando se agregan nuevos elementos.
CollectionView admite la virtualización de datos incremental a medida que se desplaza el usuario. Para obtener más información, consulta Carga incremental de datos.
Rellenar una CollectionView con datos
CollectionView se rellena con datos estableciendo su ItemsSource
propiedad en cualquier colección que implemente IEnumerable
. De forma predeterminada, CollectionView muestra los elementos de una lista vertical.
Importante
Si es necesario que CollectionView se actualice a medida que se agregan, quitan o cambian elementos en la colección subyacente, la colección subyacente debe ser una IEnumerable
colección que envíe notificaciones de cambio de propiedad, como ObservableCollection
.
CollectionView se puede rellenar con datos mediante el enlace de datos para enlazar su propiedad ItemsSource
a una colección IEnumerable
. En XAML, esto se consigue mediante la extensión de marcado Binding
.
<CollectionView ItemsSource="{Binding Monkeys}" />
El código de C# equivalente es el siguiente:
CollectionView collectionView = new CollectionView();
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");
En este ejemplo, los ItemsSource
datos de propiedad se enlazan a la Monkeys
propiedad del modelo de vista conectado.
Nota:
Los enlaces compilados se pueden habilitar para mejorar el rendimiento del enlace de datos en aplicaciones MAUI de .NET. Para obtener más información, consulta Enlaces compilados.
Para obtener información sobre cómo cambiar el diseño CollectionView, consulta Especificar el diseño CollectionView. Para obtener información sobre cómo definir la apariencia de cada elemento en CollectionView, consulta Definir la apariencia del elemento. Para obtener más información sobre el enlace de datos, consulta Enlace de datos.
Advertencia
CollectionView producirá una excepción si su ItemsSource
se actualiza fuera del subproceso de la interfaz de usuario.
Definición de la apariencia de elementos
Se puede personalizar la apariencia de cada elemento de CollectionView mediante el establecimiento de la propiedad CollectionView.ItemTemplate
en un DataTemplate:
<CollectionView ItemsSource="{Binding Monkeys}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image Grid.RowSpan="2"
Source="{Binding ImageUrl}"
Aspect="AspectFill"
HeightRequest="60"
WidthRequest="60" />
<Label Grid.Column="1"
Text="{Binding Name}"
FontAttributes="Bold" />
<Label Grid.Row="1"
Grid.Column="1"
Text="{Binding Location}"
FontAttributes="Italic"
VerticalOptions="End" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
...
</CollectionView>
El código de C# equivalente es el siguiente:
CollectionView collectionView = new CollectionView();
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");
collectionView.ItemTemplate = new DataTemplate(() =>
{
Grid grid = new Grid { Padding = 10 };
grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
Image image = new Image { Aspect = Aspect.AspectFill, HeightRequest = 60, WidthRequest = 60 };
image.SetBinding(Image.SourceProperty, "ImageUrl");
Label nameLabel = new Label { FontAttributes = FontAttributes.Bold };
nameLabel.SetBinding(Label.TextProperty, "Name");
Label locationLabel = new Label { FontAttributes = FontAttributes.Italic, VerticalOptions = LayoutOptions.End };
locationLabel.SetBinding(Label.TextProperty, "Location");
Grid.SetRowSpan(image, 2);
grid.Add(image);
grid.Add(nameLabel, 1, 0);
grid.Add(locationLabel, 1, 1);
return grid;
});
Los elementos especificados en DataTemplate definen la apariencia de cada elemento de la lista. En este ejemplo, el diseño dentro del DataTemplate se administra mediante un objeto Grid. La Grid contiene un objeto Image y dos objetos Label, que se enlazan a las propiedades de la clase Monkey
:
public class Monkey
{
public string Name { get; set; }
public string Location { get; set; }
public string Details { get; set; }
public string ImageUrl { get; set; }
}
Las capturas de pantalla siguientes muestran el resultado de crear plantillas para cada elemento de la lista:
Sugerencia
Colocar un elemento CollectionView dentro de VerticalStackLayout puede detener el desplazamiento de CollectionView y puede limitar el número de elementos que se muestran. En esta situación, reemplaza VerticalStackLayout por Grid.
Para obtener más información sobre las plantillas de datos, consulta Plantillas de datos.
Elección de la apariencia del elemento en tiempo de ejecución
La apariencia de cada elemento de CollectionView se puede elegir a la hora de ejecutarlo, en función del valor del elemento, estableciendo la propiedad CollectionView.ItemTemplate
en un objeto DataTemplateSelector:
<ContentPage ...
xmlns:controls="clr-namespace:CollectionViewDemos.Controls">
<ContentPage.Resources>
<DataTemplate x:Key="AmericanMonkeyTemplate">
...
</DataTemplate>
<DataTemplate x:Key="OtherMonkeyTemplate">
...
</DataTemplate>
<controls:MonkeyDataTemplateSelector x:Key="MonkeySelector"
AmericanMonkey="{StaticResource AmericanMonkeyTemplate}"
OtherMonkey="{StaticResource OtherMonkeyTemplate}" />
</ContentPage.Resources>
<CollectionView ItemsSource="{Binding Monkeys}"
ItemTemplate="{StaticResource MonkeySelector}" />
</ContentPage>
El código de C# equivalente es el siguiente:
CollectionView collectionView = new CollectionView
{
ItemTemplate = new MonkeyDataTemplateSelector { ... }
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");
La propiedad ItemTemplate
se establece en el objeto MonkeyDataTemplateSelector
. En el ejemplo siguiente se muestra la clase MonkeyDataTemplateSelector
:
public class MonkeyDataTemplateSelector : DataTemplateSelector
{
public DataTemplate AmericanMonkey { get; set; }
public DataTemplate OtherMonkey { get; set; }
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
return ((Monkey)item).Location.Contains("America") ? AmericanMonkey : OtherMonkey;
}
}
La clase MonkeyDataTemplateSelector
define propiedades AmericanMonkey
y OtherMonkey
DataTemplate que se establecen en diferentes modelos de datos. La invalidación de OnSelectTemplate
devuelve la AmericanMonkey
plantilla, que muestra el nombre y la ubicación del mono en verde azulado, cuando el nombre del mono contiene "America". Cuando el nombre del mono no contiene "America", la invalidación de OnSelectTemplate
devuelve la plantilla OtherMonkey
, que muestra el nombre del mono y la ubicación en plata:
Para obtener más información sobre los selectores de plantillas de datos, consulta Creación de un DataTemplateSelector.
Importante
Cuando se usa CollectionView, nunca establezcas el elemento raíz de los objetos DataTemplate en un ViewCell. Esto provocará que se produzca una excepción, porque CollectionView no tiene ningún concepto de celdas.
Menús contextuales
CollectionView admite menús contextuales para elementos de datos a través de SwipeView, que revela el menú contextual con un gesto de deslizar el dedo. El SwipeView es un control de contenedor que se ajusta alrededor de un elemento de contenido y proporciona elementos de menú contextual para ese elemento de contenido. Por lo tanto, los menús contextuales se implementan para CollectionView mediante la creación de SwipeView que define el contenido que SwipeView encapsula y los elementos del menú contextual que se muestran mediante el gesto de deslizar el dedo. Esto se logra estableciendo SwipeView como la vista raíz en que DataTemplate define la apariencia de cada elemento de datos en CollectionView:
<CollectionView x:Name="collectionView"
ItemsSource="{Binding Monkeys}">
<CollectionView.ItemTemplate>
<DataTemplate>
<SwipeView>
<SwipeView.LeftItems>
<SwipeItems>
<SwipeItem Text="Favorite"
IconImageSource="favorite.png"
BackgroundColor="LightGreen"
Command="{Binding Source={x:Reference collectionView}, Path=BindingContext.FavoriteCommand}"
CommandParameter="{Binding}" />
<SwipeItem Text="Delete"
IconImageSource="delete.png"
BackgroundColor="LightPink"
Command="{Binding Source={x:Reference collectionView}, Path=BindingContext.DeleteCommand}"
CommandParameter="{Binding}" />
</SwipeItems>
</SwipeView.LeftItems>
<Grid BackgroundColor="White"
Padding="10">
<!-- Define item appearance -->
</Grid>
</SwipeView>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
El código de C# equivalente es el siguiente:
CollectionView collectionView = new CollectionView();
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");
collectionView.ItemTemplate = new DataTemplate(() =>
{
// Define item appearance
Grid grid = new Grid { Padding = 10, BackgroundColor = Colors.White };
// ...
SwipeView swipeView = new SwipeView();
SwipeItem favoriteSwipeItem = new SwipeItem
{
Text = "Favorite",
IconImageSource = "favorite.png",
BackgroundColor = Colors.LightGreen
};
favoriteSwipeItem.SetBinding(MenuItem.CommandProperty, new Binding("BindingContext.FavoriteCommand", source: collectionView));
favoriteSwipeItem.SetBinding(MenuItem.CommandParameterProperty, ".");
SwipeItem deleteSwipeItem = new SwipeItem
{
Text = "Delete",
IconImageSource = "delete.png",
BackgroundColor = Colors.LightPink
};
deleteSwipeItem.SetBinding(MenuItem.CommandProperty, new Binding("BindingContext.DeleteCommand", source: collectionView));
deleteSwipeItem.SetBinding(MenuItem.CommandParameterProperty, ".");
swipeView.LeftItems = new SwipeItems { favoriteSwipeItem, deleteSwipeItem };
swipeView.Content = grid;
return swipeView;
});
En este ejemplo, el contenido SwipeView es un Grid que define la apariencia de cada elemento en CollectionView. Los elementos de deslizamiento se usan para realizar acciones en el contenido SwipeView y se muestran cuando el control se desliza desde el lado izquierdo:
SwipeView admite cuatro direcciones de deslizamiento diferentes, con la dirección de deslizamiento definida por la colección direccional SwipeItems
a la que se agregan los SwipeItems
objetos. De forma predeterminada, se ejecuta un elemento de deslizar el dedo cuando el usuario pulsa. Además, una vez que se ha ejecutado un elemento de deslizar el dedo, los elementos de deslizar el dedo se ocultan y se vuelve a mostrar el SwipeView contenido. No obstante, ese comportamiento se puede modificar.
Para obtener más información sobre el control de SwipeView, consulte SwipeView.
Deslizar para actualizar
CollectionView admite la funcionalidad de deslizar para actualizar en RefreshView, que permite actualizar los datos que se muestran al deslizar en la lista de elementos. El RefreshView es un control de contenedor que proporciona extracción para actualizar la funcionalidad a su elemento secundario, siempre que el elemento secundario admita contenido desplazable. Por lo tanto, la funcionalidad de deslizar para actualizar se implementa para CollectionView al establecerla como elemento secundario de RefreshView:
<RefreshView IsRefreshing="{Binding IsRefreshing}"
Command="{Binding RefreshCommand}">
<CollectionView ItemsSource="{Binding Animals}">
...
</CollectionView>
</RefreshView>
El código de C# equivalente es el siguiente:
RefreshView refreshView = new RefreshView();
ICommand refreshCommand = new Command(() =>
{
// IsRefreshing is true
// Refresh data here
refreshView.IsRefreshing = false;
});
refreshView.Command = refreshCommand;
CollectionView collectionView = new CollectionView();
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Animals");
refreshView.Content = collectionView;
// ...
Cuando el usuario inicia una actualización, se ejecuta el ICommand definido por la Command
propiedad, que debe actualizar los elementos que se muestran. Se muestra una visualización de actualización mientras se produce la actualización, que consta de un círculo de progreso animado:
El valor de la propiedad RefreshView.IsRefreshing
indica el estado actual del RefreshView. Cuando el usuario desencadena una actualización, esta propiedad pasará automáticamente a true
. Una vez completada la actualización, debe restablecer la propiedad a false
.
Para obtener más información acerca de RefreshView, consulte RefreshView.
Cargar datos de forma incremental
CollectionView admite la virtualización de datos incremental a medida que se desplaza el usuario. Esto permite escenarios como cargar de forma asincrónica una página de datos desde un servicio web, a medida que el usuario se desplaza. Además, el punto en el que se cargan más datos es configurable para que los usuarios no vean espacio en blanco o se detengan del desplazamiento.
Advertencia
No intente cargar datos de forma incremental en un CollectionView que se encuentre en un StackLayout. Este escenario hará que se produzca un bucle infinito en el que el CollectionView mantendrá la expansión.
CollectionView define las siguientes propiedades para controlar la carga incremental de datos:
RemainingItemsThreshold
, de tipoint
, el umbral de elementos que aún no están visibles en la lista en la que se desencadenará elRemainingItemsThresholdReached
evento.RemainingItemsThresholdReachedCommand
, de tipo ICommand, que se ejecuta cuando se pulsaRemainingItemsThreshold
.RemainingItemsThresholdReachedCommandParameter
, de tipoobject
, que es el parámetro que se pasa al objetoRemainingItemsThresholdReachedCommand
.
CollectionView también define un evento RemainingItemsThresholdReached
que se desencadena cuando CollectionView se desplaza lo suficientemente lejos como para que los elementos RemainingItemsThreshold
no se muestren. Este evento se puede controlar para cargar más elementos. Además, cuando se desencadena el RemainingItemsThresholdReached
evento, RemainingItemsThresholdReachedCommand
se ejecuta, lo que permite la carga incremental de datos para que tenga lugar en un modelo de vista.
El valor predeterminado de la RemainingItemsThreshold
propiedad es -1, lo que indica que el RemainingItemsThresholdReached
evento nunca se desencadenará. Cuando el valor de la propiedad es 0, el RemainingItemsThresholdReached
evento se desencadenará cuando se muestre el elemento final de ItemsSource
. Para los valores mayores que 0, el RemainingItemsThresholdReached
evento se desencadenará cuando ItemsSource
contenga ese número de elementos a los que aún no se ha desplazado.
Nota:
CollectionView valida la propiedad RemainingItemsThreshold
para que su valor sea siempre mayor o igual que -1.
En el siguiente ejemplo de XAML, se muestra una CollectionView que carga datos de forma incremental:
<CollectionView ItemsSource="{Binding Animals}"
RemainingItemsThreshold="5"
RemainingItemsThresholdReached="OnCollectionViewRemainingItemsThresholdReached">
...
</CollectionView>
El código de C# equivalente es el siguiente:
CollectionView collectionView = new CollectionView
{
RemainingItemsThreshold = 5
};
collectionView.RemainingItemsThresholdReached += OnCollectionViewRemainingItemsThresholdReached;
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Animals");
En este ejemplo de código, el evento RemainingItemsThresholdReached
se desencadena cuando todavía hay 5 elementos hasta los que no te has desplazado y, en respuesta, ejecuta el controlador de eventos OnCollectionViewRemainingItemsThresholdReached
:
void OnCollectionViewRemainingItemsThresholdReached(object sender, EventArgs e)
{
// Retrieve more data here and add it to the CollectionView's ItemsSource collection.
}
Nota:
Los datos también se pueden cargar incrementalmente enlazando la RemainingItemsThresholdReachedCommand
a una ICommand implementación en el modelo de vista.