This article has been localized into Russian by the community.
Группировка данных в элементе ListView
Как мы уже говорили ранее, WPF ListView очень гибок. Группировка это еще одна вещь, которая поддерживается "из коробки" и ее так же легко использовать и настраивать. Давайте сразу перейдем к первому примеру, где я объясню это и в дальнейшем мы сможем использовать стандартные трюки WPF для настройки внешнего вида.
Для этой статьи я позаимствовал пример кода из предыдущей статьи и расширил его для поддержки группировки. Теперь он выглядит так:
<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; }
}
}
В разметке XAML я добавил в ListView стиль GroupStyle, в котором я определяю шаблон заголовка для каждой группы. Он состоит из контрола TextBlock, где я использовал слегка увеличенный текст для выделения того что это группа - как мы увидим позднее, это может быть настроено гораздо глубже. Свойство Text контрола TextBlock привязано к свойству Name, но имейте в виду, что это НЕ свойство Name объекта данных (в нашем случае это класс User). Вместо этого, это имя группы, присвоенной WPF, основанное на свойстве, которое мы используем для разделения объектов на группы.
В коде "за сценой" мы делаем то же самое что и раньше: Мы создаем список и добавляем в него несколько экземпляров User, и затем мы привязываем (bind) список к ListView - здесь ничего нового, за исключением того, что добавлено свойство пола (Sex) пользователя.
После присваивания ItemsSource экземпляра ListView, мы используем его для получения CollectionView, которое ListView создает для нас. Это экземпляр специализированного представления, содержащий множество возможностей, включая способность группировки элементов. Мы используем это добавляя так называемый PropertyGroupDescription к набору GroupDescriptions этого представления.
Детальная настройка заголовка группы
Предыдущий пример хорошо показывает основы группировки в ListView, но выглядит скучновато, так что давайте эксплуатировать факт того, что WPF дает нам определять собственные шаблоны и оживим его. Частой задачей является возможность сворачивать и разворачивать группы, и хотя WPF не предоставляет эту возможность по-умолчанию, это несложно реализовать самостоятельно. Мы сделаем это при помощи полной замены шаблона группового контейнера.
Хоть это и выглядит немного громоздко, но используемые здесь принципы довольно просты и мы не раз встретимся с ними при изменении поведения элементов управления WPF. Код разметки:
<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>
Код "за сценой" точно такой же, как был использован в первом примере.
Теперь наши группы выглядят более интересно, и они даже включают кнопку развертывания, которая переключает видимость содержимого группы при щелчке по ней (поэтому на скриншоте не видны пользователи-женщины - я свернул соответствующую группу). Используя свойство группы ItemCount мы даже можем показать как много элементов содержит каждая группа.
Как вы можете видеть, это требует несколько более сложной разметки чем ранее, но этот пример также идет много дальше, чем это обычно делается, так что это справедливо. Когда вы читаете код, вы быстро понимаете, что большая часть строк это просто общие элементы, такие как стиль и шаблон.
Заключение
Добавить группировку в WPF ListView очень легко - все что вам необходимо это GroupStyle и HeaderTemplate, которые сообщат ListView как отрисовывать группу, и несколько строк кода "за сценой" чтобы сказать WPF по какому свойству группировать. Как вы можете видеть из последнего примера, группа может быть очень настраиваемой, позволяя вам создавать действительно классные представления без особого труда.