This article is currently in the process of being translated into Spanish (~99% done).
ListView grouping
Como lo hemos visto antes, el control ListView de WPF es muy flexible. Agrupación es otra cosa más que este control soporta de manera predeterminada, y es fácil de usar y extremadamente personalizable. Veamos nuestro primer ejemplo de una vez, lo explicaré y luego podremos utilizar trucos estándar de WPF para personalizar la apariencia aún más.
Para este artículo, tomé prestado el código de ejemplo de un artículo anterior y lo he expandido para darle soporte de agrupación. Se ve así:
<Window x:Class="WpfTutorialSamples.ListView_control.ListViewGroupSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ListViewGroupSample" Height="300" Width="300">
<Grid Margin="10">
<ListView Name="lvUsers">
<ListView.View>
<GridView>
<GridViewColumn Header="Name" Width="120" DisplayMemberBinding="{Binding Name}" />
<GridViewColumn Header="Age" Width="50" DisplayMemberBinding="{Binding Age}" />
</GridView>
</ListView.View>
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock FontWeight="Bold" FontSize="14" Text="{Binding Name}"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Data;
namespace WpfTutorialSamples.ListView_control
{
public partial class ListViewGroupSample : Window
{
public ListViewGroupSample()
{
InitializeComponent();
List<User> items = new List<User>();
items.Add(new User() { Name = "John Doe", Age = 42, Sex = SexType.Male });
items.Add(new User() { Name = "Jane Doe", Age = 39, Sex = SexType.Female });
items.Add(new User() { Name = "Sammy Doe", Age = 13, Sex = SexType.Male });
lvUsers.ItemsSource = items;
CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(lvUsers.ItemsSource);
PropertyGroupDescription groupDescription = new PropertyGroupDescription("Sex");
view.GroupDescriptions.Add(groupDescription);
}
}
public enum SexType { Male, Female };
public class User
{
public string Name { get; set; }
public int Age { get; set; }
public string Mail { get; set; }
public SexType Sex { get; set; }
}
}
En XAML, he agregado un elemento GroupStyle al ListView, en el cual defino una plantilla para el encabezado de cada grupo. El mismo consiste de un control TextBlock, donde utilizo una fuente de texto ligeramente más grande y en negrita para indicar que es un grupo - como veremos a continuación, esto puede personalizarse mucho más. La propiedad Text del TextBox está enlazadaa una propiedad llamada Name, pero por favor, observa que esta no es la propiedad Name en el objeto de datos (En este caso, la clase User). En lugar de ello, es el nombre del grupo, tal y como WPF lo asigna, basado en la propiedad que utilizamos para dividir los objetos en grupos.
En el Código subyacente, hacemos lo mismo que hicimos antes: creamos una lista y le agregamos algunos objetos de usuario y luego vinculamos la lista a ListView, nada nuevo, a excepción de la nueva propiedad Sex que agregué, que indica si el usuario es hombre o mujer.
Después de asignar un ItemSource, usamos esto para obtener un CollectionView que ListView crea para nosotros. Esta instancia de vista especializada contiene muchas posibilidades, incluida la capacidad de agrupar los elementos. Usamos esto agregando una llamada PropertyGroupDescription a GroupDescriptions de la vista. Básicamente, esto le dice a WPF que se agrupe por una propiedad específica en los objetos de datos, en este caso la propiedad Sex.
Personalizar el encabezado del grupo
El ejemplo anterior fue excelente para mostrar los conceptos básicos de la agrupación ListView, pero el aspecto era un poco aburrido, así que explotemos el hecho de que WPF nos permite definir nuestras propias plantillas y condimentar las cosas. Una solicitud común es poder colapsar y expandir el grupo, y aunque WPF no proporciona este comportamiento por defecto, es algo fácil de implementar usted mismo. Lo haremos rediseñando completamente el contenedor del grupo.
Puede parecer un poco engorroso, pero los principios utilizados son algo simples y los verá en otras situaciones cuando personalice los controles WPF. Aquí está el código:
<Window x:Class="WpfTutorialSamples.ListView_control.ListViewCollapseExpandGroupSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ListViewCollapseExpandGroupSample" Height="300" Width="300">
<Grid Margin="10">
<ListView Name="lvUsers">
<ListView.View>
<GridView>
<GridViewColumn Header="Name" Width="120" DisplayMemberBinding="{Binding Name}" />
<GridViewColumn Header="Age" Width="50" DisplayMemberBinding="{Binding Age}" />
</GridView>
</ListView.View>
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Expander IsExpanded="True">
<Expander.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" FontWeight="Bold" Foreground="Gray" FontSize="22" VerticalAlignment="Bottom" />
<TextBlock Text="{Binding ItemCount}" FontSize="22" Foreground="Green" FontWeight="Bold" FontStyle="Italic" Margin="10,0,0,0" VerticalAlignment="Bottom" />
<TextBlock Text=" item(s)" FontSize="22" Foreground="Silver" FontStyle="Italic" VerticalAlignment="Bottom" />
</StackPanel>
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
</Grid>
</Window>
El código subyacente es exactamente el mismo que se usó en el primer ejemplo; siéntase libre de desplazarse hacia arriba y agarrarlo.
Ahora nuestros grupos se ven un poco más emocionantes e incluso incluyen un botón expansor, que alternará la visibilidad de los elementos del grupo cuando hagas clic en él (es por eso que el usuario femenino único no es visible en la captura de pantalla. He colapsado ese grupo en particular). Al usar la propiedad ItemCount que el grupo expone, incluso podemos mostrar cuántos elementos consta actualmente cada grupo.
Como puede ver, requiere un poco más de marcado de lo que estamos acostumbrados, pero este ejemplo también va un poco más allá de lo que solemos hacer, por lo que parece justo. Cuando lea el código, se dará cuenta rápidamente de que muchas de las líneas son solo elementos comunes como el estilo y la plantilla.
Resumen
Agregar agrupamiento al WPF ListView es muy simple: todo lo que necesita es un GroupStyle con un HeaderTemplate, para indicarle al ListView cómo representar un grupo, y unas poca líneas de código de código subyacente para indicarle a WPF en qué propiedad agrupar. Como puede ver en el último ejemplo, el grupo es incluso muy personalizable, lo que permite crear algunas vistas realmente geniales, sin demasiado trabajo.