CellTypeDescriptor を継承すると独自のセル型を作れます。描画は IGridGraphics に対して
行うため、WinForms / WPF / Avalonia / PDF のすべてで同じコードが動きます。

実装する
using unvell.ReoGrid.Core;
using unvell.ReoGrid.Core.CellTypes;
using unvell.ReoGrid.Core.Data;
/// <summary>値を 5 段階の丸で表示するセル型。</summary>
public sealed class RatingCellType : CellTypeDescriptor
{
private readonly uint _color;
public RatingCellType(uint color = 0xFFFFC107) => _color = color;
public override string TypeName => "rating";
// 丸を描くので、セルのテキストは描画しない
public override bool ReplacesText => true;
// 直接入力させず、クリックで値を変える
public override bool AllowsTextEditing => false;
public override bool Paint(in CellTypePaintContext ctx)
{
int filled = (int)Math.Clamp(ctx.Value.AsNumber, 0, 5);
double size = Math.Min(ctx.Height - 4, 14);
double y = ctx.Y + (ctx.Height - size) / 2;
for (int i = 0; i < 5; i++)
{
double x = ctx.X + 3 + i * (size + 2);
uint color = i < filled ? _color : 0xFFDDDDDD;
ctx.Graphics.FillEllipse(x, y, size, size, color);
}
return true; // 描画したので既定の処理は不要
}
public override CellTypeClickResult OnClick(in CellTypeClickContext ctx)
{
int star = (int)(ctx.LocalX / 16) + 1;
return CellTypeClickResult.SetValue(CellValue.Number(Math.Clamp(star, 0, 5)));
}
// reogrid-json へ往復させるための設定値
public override void WriteConfig(IDictionary<string, object?> config)
=> config["color"] = _color;
}
オーバーライドできるメンバー
| メンバー | 既定 | 内容 |
|---|---|---|
TypeName | (必須) | 保存時の型名。レジストリのキーになる |
ReplacesText | true | セルのテキスト描画を行わない |
AllowsTextEditing | true | セルエディタでの直接入力を許すか |
Paint(ctx) | false | 描画。true を返すと既定の描画は行われない |
OnClick(ctx) | Unhandled | クリック時の処理 |
OnActivate(ctx) | Unhandled | Enter キーなどでの起動時の処理 |
HitRegion(...) | 0 | ホバー領域の判定(複数の当たり判定を持つ場合) |
WriteConfig(config) | 何もしない | 保存する設定値 |
描画コンテキスト
CellTypePaintContext が持つもの。
| プロパティ | 内容 |
|---|---|
Graphics | IGridGraphics(描画先) |
Row / Col | セル位置 |
X / Y / Width / Height | セルの矩形(論理ピクセル) |
Style | 実効スタイル |
Value | セル値(CellValue) |
Text | 書式適用後の表示文字列 |
TextColor | 文字色 |
HoverRegion | HitRegion が返した領域番号 |
MakeTextStyle(h, v) でセルのスタイルからテキスト描画用の設定を作れます。
クリックの結果
OnClick / OnActivate は抽象的な結果を返します。コアは UI を知らないため、
実際の動作はコントロール層が実体化します。
| 戻り値 | コントロールの動作 |
|---|---|
CellTypeClickResult.Unhandled | 何もしない |
SetValue(value) | セル値を更新(履歴にも載る) |
OpenDropdown(options) | ドロップダウンを表示 |
Navigate(url) | 既定のブラウザで開く |
RaiseButton() | CellButtonClicked を発火 |
使う
ws.SetCellType(RangePosition.Parse("C2:C100"), new RatingCellType());
ws.SetNumber(1, 2, 4); // C2 に丸 4 つ
保存と復元
reogrid-json へ往復させるには、TypeName をキーにファクトリを登録します。
// 読み込み時に型名から復元できるようにする
CellTypeRegistry.Register("rating",
config => new RatingCellType(config.GetColor("color") ?? 0xFFFFC107));
bool ok = CellTypeRegistry.IsRegistered("rating");
WriteConfig が書いた値が config として渡ります。取り出しには
GetString / GetNumber / GetBool / GetColor / GetStringArray が使えます。
登録は CellTypeRegistry に対して行うためプロセス全体で共有されます。
アプリケーションの起動時、ファイルを読み込む前に済ませてください。
未登録の型名は読み込み時に無視されます(セル値は残ります)。
状態の持ち方
記述子にセルごとの状態を持たせないでください。 1 つの記述子が範囲全体で共有されるため、 インスタンスフィールドに状態を書くとすべてのセルで同じ値になります。
セルごとに変わるものはセル値に、範囲全体で共通の設定だけを記述子のフィールドに持たせます。