ReoGrid 使用轻量级操作框架(基于 unvell.Common.ActionManager)来记录所有操作、支持撤销/重做,并允许应用程序对编辑进行分组或自定义。本指南展示如何使用内置操作、组合操作、创建自定义操作以及监控操作执行。

ReoGrid 操作的快速示例:

// 选择一个工作表
grid.CurrentWorksheet = mysheet;

// 创建一个操作(将单元格"A1"设置为 100)
var action = new SetCellDataAction("A1", 100);

// 执行操作
grid.DoAction(action);

撤销和重做上一次操作

撤销或重做操作后,CurrentWorksheet 会自动切换到所执行操作的目标工作表。

grid.Undo();  // 撤销
grid.Redo();  // 重做

使用内置操作

更新单元格值

using unvell.ReoGrid;
using unvell.ReoGrid.Actions;

var sheet = grid.CurrentWorksheet;
var action = new SetCellDataAction(2, 1, "Hello"); // 第 2 行,第 1 列(从零开始)
grid.DoAction(sheet, action);

删除行

using unvell.ReoGrid;
using unvell.ReoGrid.Actions;

var sheet = grid.CurrentWorksheet;
var deleteRows = new RemoveRowsAction(row: 5, rows: 3);
grid.DoAction(sheet, deleteRows);

执行任一调用后,ReoGrid 会推送一个撤销项。对控件执行 Undo/Redo 将自动反转或重做该操作。

有关所有工作表操作的完整列表,请参阅此处

了解操作类型

  • WorksheetAction 大多数工作表范围操作的基类。提供 Do/Undo 以及 Worksheet 引用,控件在执行前会设置该引用。

  • WorksheetReusableAction 扩展 WorksheetAction,使同一操作可以被克隆并在另一个范围上重复。ReoGrid 使用此功能支持”重复”命令。

  • WorksheetActionGroup 包装多个 WorksheetAction 实例,使它们作为单个历史项被执行和撤销。使用此功能可以将相关编辑分组(例如,更新关联列):

    var group = new WorksheetActionGroup();
    group.Actions.Add(new SetCellDataAction(row, 0, key));
    group.Actions.Add(new SetCellDataAction(row, 1, LookupPrice(key)));
    group.Actions.Add(new SetCellDataAction(row, 2, LookupDescription(key)));
    
    grid.DoAction(sheet, group); // 一个撤销项
  • WorksheetReusableActionGroup 可重复的分组版本。构造时提供目标范围:

    var repeatable = new WorksheetReusableActionGroup(new RangePosition("B2:D5"));
    repeatable.Actions.Add(new SetRangeStyleAction(repeatable.Range, new WorksheetRangeStyle
    {
        Flag = PlainStyleFlag.BackColor,
        BackColor = Color.LightYellow,
    }));
    
    grid.DoAction(sheet, repeatable);
    // 稍后可以克隆到另一个范围:
    grid.RepeatLastAction(sheet, new RangePosition("F2:H5"));

创建自定义操作

实现 WorksheetAction(如果需要重复支持则实现 WorksheetReusableAction),并重写 DoUndoGetName

using unvell.ReoGrid.Actions;

class ToggleRowHighlightAction : WorksheetAction
{
    private readonly int row;
    private bool[]? originalStates;

    public ToggleRowHighlightAction(int row) { this.row = row; }

    public override void Do()
    {
        originalStates = new bool[Worksheet.ColumnCount];
        for (int c = 0; c < Worksheet.ColumnCount; c++)
        {
            var cell = Worksheet.CreateAndGetCell(row, c);
            originalStates[c] = cell.Style.Bold;
            cell.Style.Bold = !cell.Style.Bold;
        }
    }

    public override void Undo()
    {
        if (originalStates == null) return;
        for (int c = 0; c < Worksheet.ColumnCount && c < originalStates.Length; c++)
        {
            var cell = Worksheet.CreateAndGetCell(row, c);
            cell.Style.Bold = originalStates[c];
        }
    }

    public override string GetName() => "Toggle Row Highlight";
}

像使用内置操作一样运行它:grid.DoAction(sheet, new ToggleRowHighlightAction(3));

监控操作执行

ReoGrid 公开了一些事件,您可以订阅这些事件来检查、记录或替换操作。

使用控件级事件

grid.BeforeActionPerform += (s, e) =>
{
    // e.Action 即将运行;设置 e.IsCancelled = true 可以阻止它。
};

grid.ActionPerformed += (s, e) =>
{
    // e.Action 已完成(Do/Redo)。使用 grid.Undid 和 grid.Redid 获取撤销/重做钩子。
};

grid.Undid += (s, e) => { /* 上一次操作已撤销 */ };
grid.Redid += (s, e) => { /* 上一次操作已重做 */ };

检查 ActionBehavior(Do/Undo/Redo)

底层的 ActionManager 会触发 BeforePerformActionAfterPerformAction 事件,其中 ActionEventArgs.Behavior 设置为 ActionBehavior.DoUndoRedo。当您需要这种详细级别的信息时(例如用于日志记录),请挂钩这些事件。在自定义控件中或当您可以访问 ActionManager 实例时的示例:

actionManager.AfterPerformAction += (s, e) =>
{
    switch (e.Behavior)
    {
        case ActionBehavior.Do:
            Log($"Do: {e.Action.GetName()}");
            break;
        case ActionBehavior.Undo:
            Log($"Undo: {e.Action.GetName()}");
            break;
        case ActionBehavior.Redo:
            Log($"Redo: {e.Action.GetName()}");
            break;
    }
};

取消操作并替换

您可以拦截用户操作、取消它,然后执行您自己的(可能是分组的)操作来替代:

grid.BeforeActionPerform += (s, e) =>
{
    if (e.Action is SetCellDataAction set && set.Column == 0)
    {
        e.IsCancelled = true; // 跳过默认操作

        var group = new WorksheetActionGroup();
        group.Actions.Add(set); // 保留原始编辑
        group.Actions.Add(new SetCellDataAction(set.Row, 1, "auto-fill"));
        grid.DoAction(grid.CurrentWorksheet, group);
    }
};

当关联更新应作为一个可撤销操作记录时,此模式非常有用。

跨多个工作表的操作

操作可以在同一工作簿中的不同工作表上执行。即使操作针对不同的工作表,ReoGrid 也会保留操作的执行顺序。撤销或重做操作时,无论它们针对哪个工作表,都会按照原始执行的相同顺序进行处理。

例如,如果您在 Sheet1 上更新单元格,然后在 Sheet2 上更新,撤销时将首先恢复最后一个操作(在 Sheet2 上),然后恢复前一个操作(在 Sheet1 上)。重做将按原始顺序应用它们。

158 撤销时,操作按相反顺序恢复。 159

这确保了工作簿中所有工作表的历史管理的一致性。

这篇文章对您有帮助吗?