mcpField
S
syncfusion-wpf-grouping

syncfusion-wpf-grouping

github.com/syncfusion数据与数据库5127 次安装2 周前更新
代码仓库

关于 syncfusion-wpf-grouping

此技能介绍 Syncfusion Essential Grouping,这是一个不依赖 UI 组件组织和处理表格数据的 .NET 库,面向构建分组视图、报表或处理流水线的开发者,支持层级分组、表达式筛选和汇总。

主要功能

  1. 01记录的层级分组
  2. 02标准排序与自定义排序
  3. 03基于表达式的记录筛选
  4. 04分组级聚合汇总
  5. 05通过表达式生成计算列
  6. 06高效插入、删除和移动

适用场景

  1. 01按地区或月份分组销售数据并生成报表
  2. 02按部门汇总薪资
  3. 03筛选和分析库存
  4. 04准备供导出的层级数据

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/syncfusion/wpf-ui-components-skills --skill syncfusion-wpf-grouping

安装后在 Claude Code 中输入/syncfusion-wpf-grouping确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
data-binding.md
filtering.md
getting-started.md
grouping-operations.md
sorting.md
summaries-and-expressions.md

详细介绍

为 WPF 实现 Syncfusion Essential Grouping

Syncfusion Essential Grouping 是一个 100% 原生 .NET 数据技术库,支持管理和操作表格信息,且不依赖任何特定 UI 组件。该框架可用于任何 .NET 环境,包括 C#、VB.NET 和托管 C++,非常适合需要强大数据组织能力且不依赖可视化控件的场景。

何时使用此技能

在以下情况下使用 Essential Grouping:

  • 组织和分析表格数据,而无需绑定到特定 UI 控件
  • 按一个或多个属性对数据进行分层分组(例如,按月份统计销售额、按部门分组员工)
  • 应用复杂排序,包括使用 IComparer 实现自定义排序逻辑
  • 根据使用属性、逻辑运算符和特殊运算符(LIKE、MATCH、IN、BETWEEN)的表达式筛选记录
  • 在组级别计算汇总值(Sum、Average、Min、Max、Count)
  • 使用代数公式的表达式字段添加计算列
  • 使用项具有公共属性的 IList 数据源
  • 使用二叉树数据结构高效处理大型数据集(插入/删除/移动仅需 Log2(n) 次操作)
  • 使用子组和递归数据结构创建嵌套分组

当你需要能够跨不同 UI 框架使用的数据操作能力,或需要在数据处理、报告生成、服务器端操作等非 UI 场景中使用时,GroupingEngine 尤其强大。

核心概念

架构概览

Essential Grouping 使用平衡二叉树作为核心数据结构,而不是数组。二叉树允许父分支缓存其子项的信息,从而支持:

  • 使用缓存信息快速查找位置
  • 在父分支中缓存快速汇总计算
  • 高效插入/删除/移动,仅需 Log2(n) 次操作(而 ArrayList 需要 O(n))
关键组件

Engine:管理整个数据操作流程的主要 GroupingEngine 对象

TableDescriptor:保存架构信息的对象,包含以下关键集合:

  • GroupedColumns - 用于分组的属性
  • SortedColumns - 用于排序的属性
  • Summaries - 要执行的汇总计算
  • RecordFilters - 要应用的筛选条件
  • ExpressionFields - 要添加的计算列

Table:保存实际数据,包含以下集合:

  • Records - 数据源中的所有记录
  • FilteredRecords - 应用筛选后的记录
  • TopLevelGroup - 用于访问分层数据的根组

Groups 和 Records:递归结构,其中:

  • 组包含 Groups(子组)或 Records(末端数据)
  • 通过 TopLevelGroup 进行分层导航

文档与导航指南

入门与设置

📄 阅读: references/getting-started.md

  • 先决条件与兼容性(.NET 2.0 - 4.6、VS 2015+)
  • 安装和所需程序集
  • 部署配置(Copy Local、许可)
  • 创建首个 GroupingEngine 应用程序
  • 基本项目设置和命名空间导入
数据绑定与迭代

📄 阅读: references/data-binding.md

  • IList 数据源要求
  • 创建具有公共属性的自定义对象类
  • 构建 ArrayList 数据源
  • 使用 SetSourceList 设置数据源
  • 使用 Table.Records 遍历记录
  • GetData() 方法与类型转换
分组操作

📄 阅读: references/grouping-operations.md

  • 向 GroupedColumns 集合添加属性
  • 了解 TableDescriptor 集合
  • 访问 TopLevelGroup
  • 遍历递归组结构
  • 按值检索特定组
  • Group.Groups 与 Group.Records 集合
排序(标准和自定义)

📄 阅读: references/sorting.md

  • 向 SortedColumns 集合添加属性
  • 指定排序方向(ListSortDirection)
  • SortedColumns.Add 方法重载
  • 使用 IComparer 实现自定义排序
  • 创建自定义比较器类
  • 将比较器分配给 SortColumnDescriptor
使用表达式筛选

📄 阅读: references/filtering.md

  • 创建 RecordFilterDescriptor 对象
  • 使用方括号 [] 的筛选表达式语法
  • 字符串运算符:LIKE、MATCH
  • 数值比较:=、<、>、<=、>=、<>
  • 使用 OR、AND 编写复杂表达式
  • 使用 FilteredRecords 集合
汇总和表达式字段

📄 阅读: references/summaries-and-expressions.md

  • 创建 SummaryDescriptor 对象
  • SummaryType 枚举(Int32Aggregate、DoubleAggregate 等)
  • 使用 GetSummary 获取汇总值
  • 使用 ExpressionFieldDescriptor 添加表达式字段
  • 代数表达式语法
  • 特殊运算符:MATCH、LIKE、IN、BETWEEN
  • 表达式中的自定义函数

快速入门

基本的 GroupingEngine 设置
using System;
using System.Collections;
using Syncfusion.Grouping;

namespace GroupingSample
{
    class Program
    {
        static void Main(string[] args)
        {
            // 1. Create your data source (IList with objects having public properties)
            ArrayList list = new ArrayList();
            list.Add(new Employee { Name = "John", Department = "Sales", Salary = 50000 });
            list.Add(new Employee { Name = "Jane", Department = "IT", Salary = 65000 });
            list.Add(new Employee { Name = "Bob", Department = "Sales", Salary = 55000 });
            list.Add(new Employee { Name = "Alice", Department = "IT", Salary = 70000 });

            // 2. Create GroupingEngine and set data source
            Engine groupingEngine = new Engine();
            groupingEngine.SetSourceList(list);

            // 3. Access data through Table.Records
            Console.WriteLine("All Records:");
            foreach (Record rec in groupingEngine.Table.Records)
            {
                Employee emp = rec.GetData() as Employee;
                if (emp != null)
                {
                    Console.WriteLine($"{emp.Name}, {emp.Department}, {emp.Salary}");
                }
            }

            // 4. Apply grouping
            groupingEngine.TableDescriptor.GroupedColumns.Add("Department");

            // 5. Navigate groups
            Console.WriteLine("\nGrouped by Department:");
            ShowRecordsUnderGroup(groupingEngine.Table.TopLevelGroup);

            Console.ReadLine();
        }

        static void ShowRecordsUnderGroup(Group g)
        {
            if (g.Records != null && g.Records.Count > 0)
            {
                // Terminal group - display records
                foreach (Record rec in g.Records)
                {
                    Employee emp = rec.GetData() as Employee;
                    if (emp != null)
                    {
                        Console.WriteLine($"  {emp.Name}, {emp.Department}, {emp.Salary}");
                    }
                }
            }
            else if (g.Groups != null && g.Groups.Count > 0)
            {
                // Has sub-groups - recurse
                foreach (Group subGroup in g.Groups)
                {
                    Console.WriteLine($"Group: {subGroup.Name}");
                    ShowRecordsUnderGroup(subGroup);
                }
            }
        }
    }

    public class Employee
    {
        public string Name { get; set; }
        public string Department { get; set; }
        public int Salary { get; set; }
    }
}

常见模式

模式 1:分组并计算汇总
// Group by department
groupingEngine.TableDescriptor.GroupedColumns.Add("Department");

// Add summary for salary
SummaryDescriptor salarySum = new SummaryDescriptor(
    "DeptSalaryTotal", 
    "Salary", 
    SummaryType.Int32Aggregate
);
groupingEngine.TableDescriptor.Summaries.Add(salarySum);

// Get summary for a specific group
Group itGroup = groupingEngine.Table.TopLevelGroup.Groups["IT"];
ISummary summary = itGroup.GetSummary("DeptSalaryTotal");
Int32AggregateSummary aggSummary = (Int32AggregateSummary)summary;

Console.WriteLine($"IT Department Total: {aggSummary.Sum}");
Console.WriteLine($"IT Department Average: {aggSummary.Average}");
模式 2:筛选并排序数据
// Sort by salary descending
SortColumnDescriptor sortDesc = new SortColumnDescriptor(
    "Salary", 
    ListSortDirection.Descending
);
groupingEngine.TableDescriptor.SortedColumns.Add(sortDesc);

// Filter for salaries over 60000
RecordFilterDescriptor filter = new RecordFilterDescriptor("[Salary] > 60000");
groupingEngine.TableDescriptor.RecordFilters.Add(filter);

// Access filtered records
foreach (Record rec in groupingEngine.Table.FilteredRecords)
{
    Employee emp = rec.GetData() as Employee;
    Console.WriteLine($"{emp.Name}: {emp.Salary}");
}
模式 3:添加表达式字段(计算列)
// Add a calculated bonus field (10% of salary)
ExpressionFieldDescriptor bonusField = new ExpressionFieldDescriptor(
    "Bonus", 
    "[Salary] * 0.10"
);
groupingEngine.TableDescriptor.ExpressionFields.Add(bonusField);

// Access the calculated value
foreach (Record rec in groupingEngine.Table.Records)
{
    Employee emp = rec.GetData() as Employee;
    object bonusValue = rec.GetValue("Bonus");
    Console.WriteLine($"{emp.Name}: Salary={emp.Salary}, Bonus={bonusValue}");
}
模式 4:使用 IComparer 自定义排序
// Custom comparer for case-insensitive name sorting
public class NameComparer : IComparer
{
    public int Compare(object x, object y)
    {
        if (x == null && y == null) return 0;
        if (x == null) return -1;
        if (y == null) return 1;
        
        return string.Compare(
            x.ToString(), 
            y.ToString(), 
            StringComparison.OrdinalIgnoreCase
        );
    }
}

// Apply custom comparer
NameComparer comparer = new NameComparer();
groupingEngine.TableDescriptor.SortedColumns.Add("Name");
groupingEngine.TableDescriptor.SortedColumns["Name"].Comparer = comparer;
模式 5:嵌套分组(多个级别)
// Group by Department, then by Salary range
groupingEngine.TableDescriptor.GroupedColumns.Add("Department");
groupingEngine.TableDescriptor.GroupedColumns.Add("SalaryRange");

// Navigate nested groups
foreach (Group deptGroup in groupingEngine.Table.TopLevelGroup.Groups)
{
    Console.WriteLine($"Department: {deptGroup.Name}");
    
    foreach (Group salaryGroup in deptGroup.Groups)
    {
        Console.WriteLine($"  Salary Range: {salaryGroup.Name}");
        
        foreach (Record rec in salaryGroup.Records)
        {
            Employee emp = rec.GetData() as Employee;
            Console.WriteLine($"    {emp.Name}: {emp.Salary}");
        }
    }
}

关键属性和集合

引擎属性
  • Table - 保存实际数据,并提供对 Records、FilteredRecords 和 TopLevelGroup 的访问
  • TableDescriptor - 架构信息,包含用于分组、排序、筛选和汇总的集合
TableDescriptor 集合
  • GroupedColumns - 用于分组的属性(添加多个属性时进行分层分组)
  • SortedColumns - 用于排序的属性,可选择自定义比较器
  • RecordFilters - 使用表达式语法的筛选条件
  • Summaries - 汇总计算(Sum、Average、Min、Max、Count 等)
  • ExpressionFields - 使用代数表达式计算的列
组属性
  • Groups - 子组集合(如果不是末端组)
  • Records - 记录集合(如果是末端组)
  • Name - 此组的分组值
  • GetSummary(string name) - 获取此组的汇总值
记录方法
  • GetData() - 返回底层数据对象
  • GetValue(string propertyName) - 获取属性或表达式字段的值

常见用例

  1. 销售报告:按区域/月对销售进行分组,计算总额和平均值,并筛选高价值订单
  2. 员工管理:按部门/职位分组,按薪资排序,并计算工资汇总
  3. 库存分析:按类别对产品分组,筛选库存水平,并计算价值汇总
  4. 数据导出准备:在导出到报告或其他格式之前,对数据进行分层整理
  5. 服务器端数据处理:在服务器上操作数据,不依赖 UI
  6. 多框架应用程序:在 WPF、WinForms、ASP.NET 应用程序之间共享数据逻辑
  7. 自定义报告生成器:构建包含分组和汇总的数据结构
  8. 数据验证管道:筛选和分组数据,以进行验证和质量检查

必需程序集

部署使用 Essential Grouping 的应用程序时,请确保将以下程序集复制到应用程序文件夹:

  • Syncfusion.Grouping.Base.dll
  • Syncfusion.Shared.Base.dll
  • Syncfusion.Shared.Wpf.dll

评论

支持 Markdown