WPF里ItemsControl的分组实现

时间:2022-10-30 16:05:47

我们在用到ItemsControl时,有时会用到分组。如下图所示,绑定一个普通一个数组如下所示:

数据类型为:

    public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Grades { get; set; }
    }

声明一个上述数据类型的数组并将至绑定到ItemsControl控件上,具体描述如下所示:

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <ResourceDictionary>
            <x:Array x:Key="TestList" Type="{x:Type local:Student}">
                <local:Student Id="21" Name="John" Grades="九年级"></local:Student>
                <local:Student Id="19" Name="John" Grades="八年级"></local:Student>
                <local:Student Id="56" Name="John" Grades="七年级"></local:Student>
                <local:Student Id="20" Name="John" Grades="七年级"></local:Student>
                <local:Student Id="45" Name="John" Grades="九年级"></local:Student>
                <local:Student Id="46" Name="John" Grades="九年级"></local:Student>
            </x:Array>
        </ResourceDictionary>
    </Window.Resources>
    <ItemsControl ItemsSource="{StaticResource TestList}">
       <ItemsControl.ItemTemplate>
           <DataTemplate DataType="{x:Type local:Student}">
               <StackPanel Orientation="Horizontal">
                   <TextBlock Text="{Binding Id}"></TextBlock>
                   <TextBlock Text="{Binding Name}" Margin="5,2"></TextBlock>
                   <TextBlock Text="{Binding Grades}"></TextBlock>
                </StackPanel>
           </DataTemplate>
       </ItemsControl.ItemTemplate>
    </ItemsControl>
</Window>

具体效果如下所示:
WPF里ItemsControl的分组实现

如果我们实现对上述数据按照年级(Grades)进行分组并统计每个年级的人数并按照学号(Id)进行排序,可以使用GroupStyle实现分组,具体如下所示:

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        xmlns:componentModel="clr-namespace:System.ComponentModel;assembly=WindowsBase"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <ResourceDictionary>
            <x:Array x:Key="TestList" Type="{x:Type local:Student}">
                <local:Student Id="21" Name="John" Grades="九年级"></local:Student>
                <local:Student Id="19" Name="John" Grades="八年级"></local:Student>
                <local:Student Id="56" Name="John" Grades="七年级"></local:Student>
                <local:Student Id="20" Name="John" Grades="七年级"></local:Student>
                <local:Student Id="45" Name="John" Grades="九年级"></local:Student>
                <local:Student Id="46" Name="John" Grades="九年级"></local:Student>
            </x:Array>
            <CollectionViewSource x:Key="TestListCollectionViewSource" Source="{StaticResource TestList}">
                <CollectionViewSource.SortDescriptions>
                    <!--排序描述-->
                    <componentModel:SortDescription PropertyName="Id"/>
                </CollectionViewSource.SortDescriptions>
                <CollectionViewSource.GroupDescriptions>
                    <!--分组描述-->
                    <PropertyGroupDescription PropertyName="Grades"/>
                </CollectionViewSource.GroupDescriptions>
            </CollectionViewSource>
        </ResourceDictionary>
    </Window.Resources>
    <ItemsControl ItemsSource="{Binding Source={StaticResource TestListCollectionViewSource}}">
       <ItemsControl.ItemTemplate>
           <DataTemplate DataType="{x:Type local:Student}">
               <StackPanel Orientation="Horizontal">
                   <TextBlock Text="{Binding Id}"></TextBlock>
                   <TextBlock Text="{Binding Name}" Margin="5,2"></TextBlock>
                   <TextBlock Text="{Binding Grades}"></TextBlock>
                </StackPanel>
           </DataTemplate>
       </ItemsControl.ItemTemplate>
        <ItemsControl.GroupStyle>
            <GroupStyle>
                <GroupStyle.ContainerStyle>
                    <Style TargetType="{x:Type GroupItem}">
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="{x:Type GroupItem}">
                                    <Expander IsExpanded="True"
                                              ExpandDirection="Down">
                                        <Expander.Header>
                                            <StackPanel Orientation="Horizontal">
                                                <TextBlock Text="{Binding Path=Name}"
                                                           VerticalAlignment="Center" />
                                                <TextBlock Text="{Binding Path=ItemCount, StringFormat=数量:{0}}"
                                                           VerticalAlignment="Center"
                                                           Margin="5,0,0,0" />
                                            </StackPanel>
                                        </Expander.Header>
                                        <ItemsPresenter />
                                    </Expander>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </GroupStyle.ContainerStyle>
            </GroupStyle>
        </ItemsControl.GroupStyle>
    </ItemsControl>
</Window>

具体分组排序效果如下所示:
WPF里ItemsControl的分组实现