mcpField
S
syncfusion-winforms-grouping

syncfusion-winforms-grouping

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

关于 syncfusion-winforms-grouping

用于实现 Syncfusion Grouping Engine 的技能,该 .NET 框架面向 Windows Forms 应用中的表格数据管理。它涵盖排序、筛选、分层分组、汇总和计算字段,且不依赖 UI 组件。

主要功能

  1. 01按标准或自定义规则排序
  2. 02使用逻辑和比较表达式筛选
  3. 03创建嵌套分组
  4. 04计算聚合汇总
  5. 05定义表达式计算字段

适用场景

  1. 01生成区域销售汇总
  2. 02查找库存不足的商品
  3. 03使用计算值分析客户
  4. 04筛选并分组日期记录

安装

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

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

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

包含的文件

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

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

详细介绍

实现 Syncfusion 分组引擎

Essential Grouping 是一个 100% 原生的 .NET 数据管理框架,可为表格数据提供排序、分组、筛选和汇总功能,且不依赖任何特定的 UI 组件。它专为 Windows Forms 应用程序设计。

何时使用此技能

在需要以下功能时使用此技能:

  • 对数据排序:按一个或多个属性进行排序,使用标准或自定义比较逻辑
  • 对数据分组:按属性进行分层分组,创建嵌套组
  • 筛选记录:使用代数和逻辑运算符,根据复杂表达式进行筛选
  • 汇总数据:执行聚合计算(求和、平均值、最小值、最大值、计数)
  • 添加计算字段:使用基于表达式的属性
  • 管理表格数据:处理来自任意 IList 数据源的数据(ArrayList、List、BindingList 等)
  • 构建数据驱动的应用程序:灵活地组织数据
  • 显示分组和汇总信息:不依赖 UI 控件

组件概览

分组引擎使用平衡二叉树作为核心数据结构,以高效执行数据操作。主要优势包括:

  • O(Log n) 操作:用于插入、移除和移动操作
  • 缓存父级信息:快速查找位置和汇总信息
  • 递归分组:支持多层嵌套组
  • 表达式支持:用于计算字段和筛选条件
  • 平台支持:针对 Windows Forms 应用程序进行了优化

文档与导航指南

入门与安装

📄 阅读: references/getting-started.md

  • 安装位置和部署要求
  • 创建 Windows Forms 应用程序
  • 所需的程序集引用和依赖项
  • 设置 Copy Local 属性以进行部署
  • 部署方案和 GAC 选项
  • Windows Forms 部署所需的 DLL
数据绑定基础

📄 阅读: references/data-binding.md

  • 使用公共属性创建自定义对象
  • 构建 ArrayList 和 IList 数据源
  • 使用 Engine.SetSourceList() 设置数据源
  • 遍历 Table.Records 集合
  • 使用 Record.GetData() 访问记录数据
  • 了解 Engine 和 Table 之间的关系
对数据分组

📄 阅读: references/grouping-data.md

  • 使用 TableDescriptor.GroupedColumns 集合
  • 通过 Table.TopLevelGroup 访问分组
  • 递归遍历 Groups 和 Records
  • 按键值检索特定分组
  • 了解分组层级模式
  • 分组的副作用(自动排序)
  • 显示组内的记录
对数据排序

📄 阅读: references/sorting.md

  • 将列添加到 TableDescriptor.SortedColumns
  • 指定排序方向(Ascending/Descending)
  • 使用 IComparer 接口实现自定义排序
  • 使用 SortColumnDescriptor.Comparer 属性
  • 数值与字符串排序策略
  • 多列排序场景
筛选记录

📄 阅读: references/filtering.md

  • 使用表达式创建 RecordFilterDescriptor
  • 使用 Table.FilteredRecords 集合
  • 筛选表达式语法和运算符
  • 逻辑运算符(AND、OR、NOT)
  • 比较运算符(=、<、>、<=、>=、<>)
  • 字符串运算符(LIKE、MATCH、IN、BETWEEN)
  • 构建复杂的多条件筛选器
  • 清除和更新筛选集合
表达式和汇总

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

  • 为计算字段创建 ExpressionFieldDescriptor
  • 使用属性名称编写代数表达式
  • 添加到 TableDescriptor.ExpressionFields 集合
  • 使用 Record.GetValue() 获取表达式值
  • 创建用于聚合的 SummaryDescriptor
  • 汇总类型(Int32Aggregate、DoubleAggregate 等)
  • 使用 GetSummary() 获取各分组的汇总值
  • 代数运算符和求值优先级
  • 自定义函数支持和限制

快速入门示例

using System;
using System.Collections;
using Syncfusion.Grouping;

// Define a custom data object
public class SalesRecord
{
    public string Product { get; set; }
    public string Category { get; set; }
    public int Quantity { get; set; }
    public decimal Price { get; set; }
    
    public SalesRecord(string product, string category, int qty, decimal price)
    {
        Product = product;
        Category = category;
        Quantity = qty;
        Price = price;
    }
}

// Create and populate datasource
ArrayList salesData = new ArrayList();
salesData.Add(new SalesRecord("Laptop", "Electronics", 5, 1200.00m));
salesData.Add(new SalesRecord("Mouse", "Electronics", 25, 15.00m));
salesData.Add(new SalesRecord("Desk", "Furniture", 10, 350.00m));
salesData.Add(new SalesRecord("Chair", "Furniture", 20, 150.00m));

// Create Grouping Engine and set datasource
Engine groupingEngine = new Engine();
groupingEngine.SetSourceList(salesData);

// Group by Category
groupingEngine.TableDescriptor.GroupedColumns.Add("Category");

// Add summary for Quantity
SummaryDescriptor quantitySummary = new SummaryDescriptor(
    "TotalQuantity", 
    "Quantity", 
    SummaryType.Int32Aggregate
);
groupingEngine.TableDescriptor.Summaries.Add(quantitySummary);

// Iterate through groups and display summaries
foreach (Group group in groupingEngine.Table.TopLevelGroup.Groups)
{
    Console.WriteLine($"Category: {group.Name}");
    
    // Get summary value
    var summary = group.GetSummary("TotalQuantity") as Int32AggregateSummary;
    Console.WriteLine($"Total Items: {summary.Sum}");
    
    // Display records in this group
    foreach (Record rec in group.Records)
    {
        SalesRecord sale = rec.GetData() as SalesRecord;
        Console.WriteLine($"  {sale.Product}: {sale.Quantity} @ ${sale.Price}");
    }
    Console.WriteLine();
}

常见模式

模式 1:先筛选后分组的工作流
// 1. Create engine and set datasource
Engine engine = new Engine();
engine.SetSourceList(dataList);

// 2. Apply filter first
RecordFilterDescriptor filter = new RecordFilterDescriptor("[Price] > 100");
engine.TableDescriptor.RecordFilters.Add(filter);

// 3. Then group filtered results
engine.TableDescriptor.GroupedColumns.Add("Category");

// 4. Access filtered and grouped data
foreach (Group group in engine.Table.TopLevelGroup.Groups)
{
    // Process each group
}
模式 2:多级分组
// Group by multiple columns for nested hierarchy
engine.TableDescriptor.GroupedColumns.Add("Region");
engine.TableDescriptor.GroupedColumns.Add("Category");
engine.TableDescriptor.GroupedColumns.Add("SubCategory");

// Navigate nested groups recursively
void ProcessGroup(Group group, int level)
{
    if (group.Records != null && group.Records.Count > 0)
    {
        // Terminal group with records
        foreach (Record rec in group.Records)
        {
            // Process record
        }
    }
    else if (group.Groups != null && group.Groups.Count > 0)
    {
        // Parent group with sub-groups
        foreach (Group subGroup in group.Groups)
        {
            ProcessGroup(subGroup, level + 1);
        }
    }
}
模式 3:动态表达式字段
// Add calculated column for total value
ExpressionFieldDescriptor totalExpr = new ExpressionFieldDescriptor(
    "TotalValue", 
    "[Quantity] * [Price]"
);
engine.TableDescriptor.ExpressionFields.Add(totalExpr);

// Use expression in filter
RecordFilterDescriptor highValueFilter = new RecordFilterDescriptor(
    "[TotalValue] > 1000"
);
engine.TableDescriptor.RecordFilters.Add(highValueFilter);

// Retrieve expression values
foreach (Record rec in engine.Table.FilteredRecords)
{
    decimal total = (decimal)rec.GetValue("TotalValue");
    Console.WriteLine($"Total: ${total}");
}
模式 4:使用 IComparer 自定义排序
// Implement custom comparer
public class CustomComparer : IComparer
{
    public int Compare(object x, object y)
    {
        // Custom comparison logic
        string str1 = x.ToString();
        string str2 = y.ToString();
        
        // Example: Sort by length first, then alphabetically
        int lengthCompare = str1.Length.CompareTo(str2.Length);
        return lengthCompare != 0 ? lengthCompare : str1.CompareTo(str2);
    }
}

// Apply custom sort
engine.TableDescriptor.SortedColumns.Add("Product");
engine.TableDescriptor.SortedColumns["Product"].Comparer = new CustomComparer();

关键属性和集合

Engine 类
属性描述
Table获取包含记录和分组的 Table 对象
TableDescriptor获取架构信息和配置
SetSourceList(IList)设置引擎的数据源
TableDescriptor 属性
属性描述
GroupedColumns要分组的属性集合
SortedColumns要排序的属性集合
RecordFilters筛选条件集合
Summaries汇总计算集合
ExpressionFields计算字段集合
Table 属性
属性描述
Records表中的所有记录
FilteredRecords应用筛选条件后的记录
TopLevelGroup用于分层访问的根分组
Group 类
属性描述
Groups子分组(用于父分组)
Records此分组中的记录(用于末级分组)
Name分组键/名称
GetSummary(string)按名称获取汇总值
Record 类
方法描述
GetData()返回底层数据对象
GetValue(string)按名称获取属性值或表达式值

常见用例

用例 1:按地区和产品生成销售报告
// Group sales by region, then product category
engine.TableDescriptor.GroupedColumns.Add("Region");
engine.TableDescriptor.GroupedColumns.Add("ProductCategory");

// Add sales summaries
engine.TableDescriptor.Summaries.Add(
    new SummaryDescriptor("TotalSales", "SalesAmount", SummaryType.DoubleAggregate)
);
engine.TableDescriptor.Summaries.Add(
    new SummaryDescriptor("OrderCount", "OrderID", SummaryType.Count)
);
用例 2:筛选低库存商品
// Filter for items below reorder level
RecordFilterDescriptor lowStock = new RecordFilterDescriptor(
    "[StockLevel] < [ReorderLevel] AND [Active] = 1"
);
engine.TableDescriptor.RecordFilters.Add(lowStock);

// Sort by urgency (stock level ascending)
engine.TableDescriptor.SortedColumns.Add("StockLevel", ListSortDirection.Ascending);
用例 3:使用计算字段分析客户
// Add expression for customer value
ExpressionFieldDescriptor customerValue = new ExpressionFieldDescriptor(
    "CustomerValue",
    "[TotalOrders] * [AverageOrderAmount]"
);
engine.TableDescriptor.ExpressionFields.Add(customerValue);

// Filter for high-value customers
RecordFilterDescriptor premiumCustomers = new RecordFilterDescriptor(
    "[CustomerValue] > 10000"
);
engine.TableDescriptor.RecordFilters.Add(premiumCustomers);

// Group by customer tier
engine.TableDescriptor.GroupedColumns.Add("Tier");
用例 4:基于时间的数据分析
// Filter for date range using BETWEEN operator
RecordFilterDescriptor dateRange = new RecordFilterDescriptor(
    "[OrderDate] BETWEEN {1/1/2024, 12/31/2024}"
);
engine.TableDescriptor.RecordFilters.Add(dateRange);

// Group by month (requires calculated field)
ExpressionFieldDescriptor monthField = new ExpressionFieldDescriptor(
    "OrderMonth",
    "Month([OrderDate])"
);
engine.TableDescriptor.ExpressionFields.Add(monthField);
engine.TableDescriptor.GroupedColumns.Add("OrderMonth");

边缘情况和故障排除

空分组

筛选后分组可能为空。迭代前请始终检查 Records.Count。

表达式中的类型不匹配

属性值必须与运算类型匹配:

  • 数值比较使用 =
  • 字符串比较使用 LIKE 或 MATCH
  • 使用适当的汇总类型(Int32Aggregate 与 DoubleAggregate)
递归导航

递归导航分组时,请检查 group.Groups 或 group.Records 是否已填充。每个层级中只有其中一个会包含项。

筛选表达式语法
  • 属性名称必须用方括号括起来:[PropertyName]
  • 字符串字面量必须用单引号括起来:'value'
  • IN 运算符列表中的空格有意义:{value1,value2},而不是 {value1, value2}
内存管理

Grouping Engine 会维护内部数据结构。完成后调用 Dispose() 以释放资源。

最佳实践

  1. 配置前设置数据源:添加分组、排序或筛选条件前,先调用 SetSourceList()
  2. 使用 FilteredRecords 获取筛选后的数据:筛选条件生效时,访问 Table.FilteredRecords,而非 Table.Records
  3. 选择合适的汇总类型:使汇总类型与属性的数据类型(Int32、Double、Boolean 等)相匹配
  4. 优化表达式:复杂表达式会影响性能;尽可能保持简单
  5. 处理 null 值:使用 GetData() 访问记录数据时,检查是否为 null
  6. 正确释放资源:不再需要 Engine 对象时,将其释放
  7. 测试筛选表达式:部署前验证筛选语法,避免运行时错误

平台特定说明

Windows Forms
  • 分组引擎可独立运行,也可与 GridGroupingControl 配合使用
  • 无需 UI 依赖项
  • 针对桌面应用场景进行了优化

后续步骤

  1. 阅读 getting-started.md,了解安装和设置
  2. 查看 data-binding.md,了解数据源要求
  3. 根据需要,查阅相应的参考文件以了解具体功能
  4. 查看各参考文件中的代码示例,了解实现细节

评论

支持 Markdown