Actions

edit

An action is an IUndoRedoAction: it applies a change in ExecuteAsync and reverts it in UnExecuteAsync. The manager calls them in turn: ExecuteAsync when the action is recorded (or when its transaction is committed) and when it is redone, UnExecuteAsync when it is undone.

Delegates or a class

You writeUse it when
The delegate overloads of RecordActionAsyncThe change is a few lines of code at one place
new UndoRedoDelegateAction(execute, unexecute)The same, with a Description or AllowToMergeWithPrevious
A class that derives from UndoRedoActionBaseThe same kind of change is recorded from several places, or it needs state, such as a merge
A class that implements IUndoRedoActionYou need full control over the state of the action

Write an action class

Derive from UndoRedoActionBase and implement ExecuteCoreAsync and UnExecuteCoreAsync:

internal sealed class AddItemAction(IList<int> list, int value) : UndoRedoActionBase
{
    protected override ValueTask ExecuteCoreAsync(CancellationToken cancellationToken)
    {
        list.Add(value);
        return ValueTask.CompletedTask;
    }

    protected override ValueTask UnExecuteCoreAsync(CancellationToken cancellationToken)
    {
        list.Remove(value);
        return ValueTask.CompletedTask;
    }
}

Record it like any other action:

await manager.RecordActionAsync(new AddItemAction(list, 42));

UndoRedoActionBase tracks whether the action is applied. ExecuteAsync throws an InvalidOperationException when the action is already applied, and UnExecuteAsync when it is not. So an action instance can be recorded only once at a time: recording the same instance twice would add an undo step that reverts nothing. Create a new instance for each change.

Describe an action

Set Description to the text to show in an undo history, such as "Add circle". The manager exposes the recorded actions through UndoableActions and RedoableActions: see Undo history in the UI.

UndoRedoActionBase.Description is virtual, so an action class can compute the text from its state. For an action that implements IUndoRedoAction directly, Description returns null unless you implement it.

Rules for actions