You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用ListCollectionView的GroupBySelector属性?求测试示例代码

我完全懂这种冷门WPF特性找不到实际示例的痛苦!ListCollectionView.GroupBySelector和它的GroupDescriptionSelectorCallback回调确实是个藏得很深的功能,文档提了但几乎没人分享可运行的代码。我刚写了一个经过测试的完整示例,直接就能跑,给你演示怎么用它实现动态分组逻辑!

完整可测试示例:动态分组逻辑实现

1. 定义数据模型

先搞个简单的Person类,包含我们要用来分组的核心属性:

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string City { get; set; }
}

2. ViewModel与核心分组逻辑

这里是实现动态分组的关键——我们创建ViewModel准备测试数据,然后初始化ListCollectionView并绑定GroupBySelector:

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using System.Windows.Data;

public class MainViewModel : INotifyPropertyChanged
{
    private ObservableCollection<Person> _people;
    public ObservableCollection<Person> People
    {
        get => _people;
        set
        {
            _people = value;
            OnPropertyChanged(nameof(People));
            InitializeGroupedView();
        }
    }

    public ICollectionView GroupedPeopleView { get; private set; }

    public MainViewModel()
    {
        // 初始化测试数据
        People = new ObservableCollection<Person>
        {
            new Person { Name = "张三", Age = 16, City = "北京" },
            new Person { Name = "李四", Age = 30, City = "上海" },
            new Person { Name = "王五", Age = 65, City = "北京" },
            new Person { Name = "赵六", Age = 22, City = "广州" },
            new Person { Name = "孙七", Age = 17, City = "上海" },
            new Person { Name = "周八", Age = 70, City = "广州" }
        };
    }

    private void InitializeGroupedView()
    {
        GroupedPeopleView = new ListCollectionView(People);

        // 绑定GroupBySelector,核心回调逻辑在这里!
        GroupedPeopleView.GroupBySelector = new GroupDescriptionSelectorCallback(SelectDynamicGroup);
    }

    // 关键:针对每一项返回对应的分组规则
    private GroupDescription SelectDynamicGroup(object item, int level)
    {
        var person = item as Person;
        if (person == null) return null;

        // 根据年龄动态生成分组名称
        string ageGroup = person.Age switch
        {
            < 18 => "未成年人(<18岁)",
            <= 60 => "成年人(18-60岁)",
            _ => "老年人(>60岁)"
        };

        // 返回自定义分组规则,用转换器映射到我们的分组名称
        return new PropertyGroupDescription(null, new AgeGroupConverter(ageGroup));
    }

    // 自定义转换器:将每个Person映射到对应的分组键
    private class AgeGroupConverter : IValueConverter
    {
        private readonly string _groupName;

        public AgeGroupConverter(string groupName) => _groupName = groupName;

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            => _groupName;

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            => throw new NotImplementedException();
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
        => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

3. XAML布局(显示分组效果)

最后在MainWindow的XAML里绑定数据,配置ListView显示分组:

<Window x:Class="WpfGroupBySelectorDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfGroupBySelectorDemo"
        Title="GroupBySelector动态分组示例" Height="450" Width="800">
    <Window.DataContext>
        <local:MainViewModel />
    </Window.DataContext>
    <Grid>
        <ListView ItemsSource="{Binding GroupedPeopleView}">
            <!-- 配置分组头部样式 -->
            <ListView.GroupStyle>
                <GroupStyle>
                    <GroupStyle.HeaderTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Name}" 
                                       FontSize="14" FontWeight="Bold" 
                                       Foreground="#2c3e50" Margin="5"/>
                        </DataTemplate>
                    </GroupStyle.HeaderTemplate>
                </GroupStyle>
            </ListView.GroupStyle>

            <!-- 列表项模板 -->
            <ListView.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" Margin="10,5">
                        <TextBlock Text="{Binding Name}" Width="80"/>
                        <TextBlock Text="{Binding Age}" Width="50"/>
                        <TextBlock Text="{Binding City}"/>
                    </StackPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Window>

核心逻辑说明

  • GroupBySelector是一个回调委托,针对集合中的每一项调用SelectDynamicGroup方法,返回对应的GroupDescription
  • 你可以根据项的任意属性(比如这里的Age)动态决定分组规则,甚至可以利用level参数实现多级分组(比如先按年龄组,再按城市)
  • 示例中用自定义转换器是为了实现完全自定义的分组名称;如果只是按现有属性分组,直接用new PropertyGroupDescription("PropertyName")即可

运行效果

启动程序后,你会看到ListView自动将人员分成三个组:未成年人(<18岁)、成年人(18-60岁)、老年人(>60岁),每个组下面显示对应的人员信息,完全符合我们的动态分组逻辑!

内容的提问来源于stack exchange,提问作者l33t

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 10:00:30