syncfusion-wpf-grouping について
このスキルは、UI コンポーネントに依存せず表形式データを整理・操作する .NET ライブラリ、Syncfusion Essential Grouping を解説します。グループ化ビュー、レポート、処理パイプラインを作る開発者向けで、階層グループ、式によるフィルター、集計に対応します。
主な機能
- 01レコードの階層グループ化
- 02標準ソートとカスタムソート
- 03式によるレコードフィルター
- 04グループ単位の集計
- 05式による計算列の追加
- 06効率的な挿入・削除・移動
活用シーン
- 01売上データを地域や月でまとめてレポート化
- 02部門ごとの給与集計
- 03在庫のフィルタリングと分析
- 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.mdfiltering.mdgetting-started.mdgrouping-operations.mdsorting.mdsummaries-and-expressions.md詳細
WPF 向け Syncfusion Essential Grouping の実装
Syncfusion Essential Grouping は、特定の UI コンポーネントに依存せずに表形式の情報を管理、操作できる、100%ネイティブな .NET データテクノロジーライブラリです。このフレームワークは、C#、VB.NET、マネージド C++ など、あらゆる .NET 環境で使用できるため、視覚的なコントロールに依存せずに高度なデータ整理機能が必要なシナリオに最適です。
このスキルを使用する場面
次のような場合は、Essential Grouping を使用してください。
- 特定の UI コントロールにバインドせずに、表形式のデータを整理、分析する
- 1 つ以上のプロパティでデータを階層的にグループ化する(例:月別の売上、部署別の従業員)
- IComparer の実装によるカスタム並べ替えロジックなど、複雑な並べ替えを適用する
- プロパティ、論理演算子、特殊演算子(LIKE、MATCH、IN、BETWEEN)を使った式に基づいてレコードをフィルターする
- グループレベルで集計(合計、平均、最小、最大、件数)を計算する
- 代数式を使った式フィールドで計算列を追加する
- 項目がパブリックプロパティを持つ IList データソースを扱う
- 二分木データ構造(挿入/削除/移動に Log2(n) 回の操作)を使用して、大規模なデータセットを効率的に処理する
- サブグループと再帰的なデータ構造で、ネストされたグループ化を作成する
GroupingEngine は、異なる UI フレームワーク間で機能するデータ操作機能が必要な場合や、データ処理、レポート作成、サーバー側の処理など、UI を使用しないシナリオで特に強力です。
基本概念
アーキテクチャの概要
Essential Grouping は、配列ではなく、コアデータ構造として平衡二分木を使用します。二分木では、親ブランチに子の情報をキャッシュできるため、次のことが可能になります。
- キャッシュされた情報によるすばやい位置検索
- 親ブランチにキャッシュされた高速な集計計算
- Log2(n) 回の操作で済む効率的な挿入/削除/移動(ArrayList の場合は O(n))
主なコンポーネント
Engine:データ操作パイプライン全体を管理する、メインの GroupingEngine オブジェクト
TableDescriptor:次のキーコレクションを含むスキーマ情報の保持オブジェクト:
GroupedColumns- グループ化するプロパティSortedColumns- 並べ替えるプロパティSummaries- 実行する集計計算RecordFilters- 適用するフィルター条件ExpressionFields- 追加する計算列
Table:次のコレクションを含む実データの保持オブジェクト:
Records- データソースのすべてのレコードFilteredRecords- フィルター適用後のレコードTopLevelGroup- 階層データにアクセスするためのルートグループ
グループとレコード:次のような再帰的構造:
- グループには、
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)- プロパティまたは式フィールドの値を取得します
一般的なユースケース
- 売上レポート:地域や月ごとに売上をグループ化し、合計と平均を計算して、高額注文をフィルタリングします
- 従業員管理:部署や役職ごとにグループ化し、給与で並べ替えて、給与計算の集計値を算出します
- 在庫分析:カテゴリごとに商品をグループ化し、在庫数をフィルタリングして、金額の集計値を算出します
- データエクスポートの準備:レポートやその他の形式にエクスポートする前に、データを階層的に整理します
- サーバー側のデータ処理:UI に依存せずにサーバー上でデータを操作します
- 複数フレームワーク対応アプリケーション:WPF、WinForms、ASP.NET アプリケーション間でデータロジックを共有します
- カスタムレポート生成ツール:グループ化と集計を含むレポートデータ構造を構築します
- データ検証パイプライン:検証と品質チェックのためにデータをフィルタリングしてグループ化します
必要なアセンブリ
Essential Grouping を使用するアプリケーションをデプロイする際は、次のアセンブリがアプリケーションフォルダーにコピーされていることを確認してください。
Syncfusion.Grouping.Base.dllSyncfusion.Shared.Base.dllSyncfusion.Shared.Wpf.dll