Agrupación de Xamarin.Forms CollectionView
Los conjuntos de datos de gran tamaño a menudo se pueden volver inconfundibles cuando se presentan en una lista de desplazamiento continuo. En este escenario, la organización de los datos en grupos puede mejorar la experiencia del usuario al facilitar la navegación por los datos.
CollectionView
admite la visualización de datos agrupados y define las siguientes propiedades que controlan cómo se presentará:
IsGrouped
, de tipobool
, indica si los datos subyacentes deben mostrarse en grupos. El valor predeterminado de esta propiedad esfalse
.GroupHeaderTemplate
, de tipoDataTemplate
, la plantilla que se va a usar para el encabezado de cada grupo.GroupFooterTemplate
, de tipoDataTemplate
, la plantilla que se va a usar para el pie de página de cada grupo.
Todas estas propiedades están respaldadas por objetos BindableProperty
, lo que significa que las propiedades pueden ser destinos de los enlaces de datos.
En las capturas de pantalla siguientes se muestra un objeto CollectionView
que muestra datos agrupados:
Para obtener más información sobre las plantillas de datos, consulte Plantillas de datos de Xamarin.Forms.
Agrupación de datos
Los datos se deben agrupar antes de que se puedan mostrar. Esto se puede lograr mediante la creación de una lista de grupos, donde cada grupo es una lista de elementos. La lista de grupos debe ser una colección de IEnumerable<T>
, donde T
define dos fragmentos de datos:
- Nombre de grupo.
- Una colección
IEnumerable
que define los elementos que pertenecen al grupo.
El proceso de agrupación de datos, por lo tanto, consiste en:
- Crear un tipo que modele un solo elemento.
- Crear un tipo que modele un único grupo de elementos.
- Crear una colección
IEnumerable<T>
, dondeT
es el tipo que modela un único grupo de elementos. Por tanto, esta es una colección de grupos, que almacena los datos agrupados. - Agregar un elemento a la colección
IEnumerable<T>
.
Ejemplo
Al agrupar datos, el primer paso es crear un tipo que modele un solo elemento. El ejemplo siguiente muestra la clase Animal
para la aplicación de ejemplo:
public class Animal
{
public string Name { get; set; }
public string Location { get; set; }
public string Details { get; set; }
public string ImageUrl { get; set; }
}
La clase Animal
modela un solo elemento. Luego se puede crear un tipo que modele un grupo de elementos. El ejemplo siguiente muestra la clase AnimalGroup
de la aplicación de ejemplo:
public class AnimalGroup : List<Animal>
{
public string Name { get; private set; }
public AnimalGroup(string name, List<Animal> animals) : base(animals)
{
Name = name;
}
}
La clase AnimalGroup
hereda de la clase List<T>
y agrega una propiedad Name
que representa el nombre del grupo.
Después se puede crear una colección de grupos IEnumerable<T>
:
public List<AnimalGroup> Animals { get; private set; } = new List<AnimalGroup>();
Este código define una colección denominada Animals
, donde cada elemento de la colección es un objeto AnimalGroup
. Cada objeto AnimalGroup
consta de un nombre y una colección List<Animal>
que define los objetos del grupo Animal
.
Los datos agrupados se pueden agregar a la colección Animals
después:
Animals.Add(new AnimalGroup("Bears", new List<Animal>
{
new Animal
{
Name = "American Black Bear",
Location = "North America",
Details = "Details about the bear go here.",
ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/0/08/01_Schwarzbär.jpg"
},
new Animal
{
Name = "Asian Black Bear",
Location = "Asia",
Details = "Details about the bear go here.",
ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b7/Ursus_thibetanus_3_%28Wroclaw_zoo%29.JPG/180px-Ursus_thibetanus_3_%28Wroclaw_zoo%29.JPG"
},
// ...
}));
Animals.Add(new AnimalGroup("Monkeys", new List<Animal>
{
new Animal
{
Name = "Baboon",
Location = "Africa & Asia",
Details = "Details about the monkey go here.",
ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Papio_anubis_%28Serengeti%2C_2009%29.jpg/200px-Papio_anubis_%28Serengeti%2C_2009%29.jpg"
},
new Animal
{
Name = "Capuchin Monkey",
Location = "Central & South America",
Details = "Details about the monkey go here.",
ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/4/40/Capuchin_Costa_Rica.jpg/200px-Capuchin_Costa_Rica.jpg"
},
new Animal
{
Name = "Blue Monkey",
Location = "Central and East Africa",
Details = "Details about the monkey go here.",
ImageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/BlueMonkey.jpg/220px-BlueMonkey.jpg"
},
// ...
}));
Este código crea dos grupos en la colección Animals
. El primer AnimalGroup
se denomina Bears
y contiene una colección List<Animal>
de detalles de osos. El segundo AnimalGroup
se llama Monkeys
y contiene una colección List<Animal>
de detalles de mono.
Visualización de datos agrupados
CollectionView
mostrará los datos agrupados, siempre que los datos se hayan agrupado correctamente, estableciendo la propiedad IsGrouped
en true
:
<CollectionView ItemsSource="{Binding Animals}"
IsGrouped="true">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="10">
...
<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
{
IsGrouped = true
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Animals");
// ...
La apariencia de cada elemento en CollectionView
se define estableciendo la propiedad CollectionView.ItemTemplate
en DataTemplate
. Para obtener más información, consulta Definir la apariencia del elemento.
Nota:
De forma predeterminada, CollectionView
mostrará el nombre del grupo en el encabezado y pie de página del grupo. Este comportamiento se puede cambiar personalizando el encabezado de grupo y el pie de página de grupo.
Personalización del encabezado de grupo
Se puede personalizar la apariencia de cada encabezado de grupo mediante el establecimiento de la propiedad CollectionView.GroupHeaderTemplate
en DataTemplate
:
<CollectionView ItemsSource="{Binding Animals}"
IsGrouped="true">
...
<CollectionView.GroupHeaderTemplate>
<DataTemplate>
<Label Text="{Binding Name}"
BackgroundColor="LightGray"
FontSize="Large"
FontAttributes="Bold" />
</DataTemplate>
</CollectionView.GroupHeaderTemplate>
</CollectionView>
En este ejemplo, cada encabezado de grupo se establece en una Label
que muestra el nombre del grupo y que tiene otras propiedades de apariencia establecidas. En las capturas de pantalla siguientes se muestra el encabezado de grupo personalizado:
Personalización del pie de página del grupo
Se puede personalizar la apariencia de cada pie de página del grupo estableciendo la propiedad CollectionView.GroupFooterTemplate
en DataTemplate
:
<CollectionView ItemsSource="{Binding Animals}"
IsGrouped="true">
...
<CollectionView.GroupFooterTemplate>
<DataTemplate>
<Label Text="{Binding Count, StringFormat='Total animals: {0:D}'}"
Margin="0,0,0,10" />
</DataTemplate>
</CollectionView.GroupFooterTemplate>
</CollectionView>
En este ejemplo, cada pie de página del grupo se establece en un objeto Label
que muestra el número de elementos del grupo. En las capturas de pantalla siguientes se muestra el pie de página de grupo personalizado:
Grupos vacíos
Cuando CollectionView
muestra datos agrupados, se mostrarán todos los grupos que estén vacíos. Estos grupos se mostrarán con un encabezado de grupo y un pie de página, lo que indica que el grupo está vacío. En las capturas de pantalla siguientes se muestra un grupo vacío:
Nota:
En iOS 10 y versiones inferiores, los encabezados y pies de página de grupo para grupos vacíos se pueden mostrar en la parte superior de CollectionView
.
Agrupar sin plantillas
CollectionView
puede mostrar datos agrupados correctamente sin establecer la propiedad CollectionView.ItemTemplate
en una DataTemplate
:
<CollectionView ItemsSource="{Binding Animals}"
IsGrouped="true" />
En este escenario, se pueden mostrar datos significativos reemplazando el método ToString
en el tipo que modela un solo elemento y el tipo que modela un único grupo de elementos.