Xamarin.Forms Datos de CollectionView
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 tipoDataTemplate
, 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.
Nota:
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 pueden habilitarse para mejorar el rendimiento del enlace de datos en aplicaciones de Xamarin.Forms. Para obtener más información, vea Enlaces compilados.
Para obtener información sobre cómo cambiar el diseño de CollectionView
, vea Xamarin.Forms Diseño de 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, consulte Enlace de datos de Xamarin.Forms.
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.Children.Add(image);
grid.Children.Add(nameLabel, 1, 0);
grid.Children.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:
Para obtener más información sobre las plantillas de datos, consulte Plantillas de datos de Xamarin.Forms.
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 DataTemplate
AmericanMonkey
y OtherMonkey
que se establecen en diferentes plantillas 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 más información sobre los selectores de plantillas de datos, consulte Creación de una instancia de Xamarin.Forms 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 = Color.White };
// ...
SwipeView swipeView = new SwipeView();
SwipeItem favoriteSwipeItem = new SwipeItem
{
Text = "Favorite",
IconImageSource = "favorite.png",
BackgroundColor = Color.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 = Color.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 Xamarin.Forms 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 Xamarin.FormsRefreshView.
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.
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 tipoICommand
, 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.