TOC

This article is currently in the process of being translated into Vietnamese (~90% done).

ListView:

Phân nhóm trong ListView

Như chúng ta đã nói trước đây, WPF ListView rất linh động. Grouping (nhóm) là một thứ hỗ trợ chúng ta vượt ra ngoài các giới hạn, và nó dễ sử dụng cũng như có tính tùy chỉnh cực kỳ cao. Chúng ta hãy cùng vào thằng ví dụ đầu tiên, sau đó tôi sẽ giải thích về nó và tiếp đến là những thủ thuật để tùy chỉnh sâu hơn về cách mà nó hiển thị.

Trong bài viết này, chúng ta mượn các đoạn code từ các bài viết trước và mở rộng nó cho grouping (nhóm). Cụ thể như sau:

<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; }
	}
}

Trong XAML, tôi đã thêm vào một GroupStyle cho ListView, trong đó định nghĩa một template cho tiêu đề của mỗi nhóm. Nó bao gồm một TextBlock với chữ lớn hơn một chút và được tô đậm để có thể dễ dàng nhận biết được đó là một nhóm - và tất nhiên là chúng ta có thể tùy chỉnh nó nhiều hơn thế. Thuộc tính Text của TextBlock được bind đến thuộc tính Name, nhưng lưu ý thuộc tính Name này không phải thuộc tính của data object (trong trường hợp này là class User). Thay vào đó, nó là tên của nhóm, được gán bởi WPF, dựa trên thuộc tính mà chúng ta sử dụng để phân thành các nhóm.

Trong phần code-behind, chúng ta làm giống với trước đây: tạo một danh sách các User, sau đó bind danh sách đó đến ListView, trừ việc tôi thêm vào thuộc tính Sex để xác định user đó là nam hay nữ.

Sau khi gán dữ liệu cho ItemsSource, chúng ta sử dụng nó để lấy một CollectionView mà ListView tạo giúp chúng ta. View đặc biệt này có nhiều khả năng, trong đó có khả năng nhóm các mục lại với nhau, Để làm được như vậy, chúng ta thêm một PropertyGroupDescription vào GroupDescriptions của View đã lấy được. PropertyGroupDescription chỉ rõ thuộc tính nào của data object sẽ được sử dụng để phân nhóm, trong trường hợp này là thuộc tính Sex.

Customizing the group header

Ví dụ trên khá là tuyệt vời khi nó cho thấy những thứ cơ bản đối với việc phân nhóm trong ListView, nhưng mà giao diện trông hơi nhàm chán, trong khi WPF cho phép chúng ta tạo ra các template để làm cho nó đẹp hơn. Một yêu cầu phổ biến đối với một group là khả năng thu gọn và mở rộng, trong khi WPF mặc định không cung cấp điều này, bạn vẫn có thể triển khai khả năng đó khá là dễ dàng. Chúng ta làm điều đó bằng cách định nghĩa lại template cho group container.

Nó có thể trông hơi rườm rà, nhưng mà các nguyên tắc được sử dụng khá là đơn giản và bạn sẽ thấy chúng trong khi mà bạn thực hiện tùy biến các WPF control.

<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>

Bạn có thể sử dụng lại phần code-behind do nó hoàn toàn giống với ví dụ đầu tiên.

Bây giờ thì các nhóm của chúng ta trông hấp dẫn hơn một chút, thậm chí là có cả một nút mở rộng cho phép chúng ta ẩn/hiện các mục trong nhóm (như bạn có thể thấy trong hình tôi đã thu gọn nhóm Female làm cho các mục trong nhóm này bị ẩn đi). Bằng cách sử dụng thuộc tính ItemCount, chúng ta còn có thể hiển thị được có bao nhiêu mục trong mỗi nhóm.

As you can see, it requires a bit more markup than we're used to, but this example also goes a bit beyond what we usually do, so that seems fair. When you read through the code, you will quickly realize that many of the lines are just common elements like style and template.

Tổng kết

Thêm Grouping vào trong WPF ListView rất đơn giản - tất cả những gì bạn cần là một GroupStyle cùng với một HeaderTemplate, dùng để chỉ cho ListView cách hiển thị một nhóm, và cũng phải cần thêm một số dòng code-behind để xác định việc gom nhóm sẽ dựa trên thuộc tính nào. Như bạn có thể thấy ở ví dụ cuối, các nhóm có thể được tùy biến nhiều hơn nữa, cho phép bạn tạo ra các các hiển thị thực sự rất ngầu mà không phải bỏ ra quá nhiều công sức.

This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!