IUndoStack interface Core
Grid-wide undo/redo as a CONTRACT, not a concrete table type.
This is the pattern every serious grid and editor converges on: ONE history service holding inverse-operation entries (command pattern), fed at the model's commit choke point, with batch brackets so a composite gesture undoes as a single step. A template that owns mutations (a table, a timeline drag, a chart edit) implements this, and the grid wiring, the toolbar commands and the shortcut all talk to the contract.
IUndoStack.Record is the seam for STRUCTURAL changes that do not travel through a cell write (move an activity, split an interval, insert a row): the caller hands the two closures, the implementation owns ordering, capping and the redo-invalidation rule (a new entry clears the redo side). Implementations must ignore a IUndoStack.Record that happens while a replay is running — the undo of an undo is the redo entry it came from, not a fresh recording. Batch brackets stay on ISlotModel.BeginEditBatch/ISlotModel.EndEditBatch: they scope CELL commits and recordings alike, so a drag that writes two cells and records one structural entry still undoes as one step.
public interface IUndoStack
- Namespace
- ArionUI.Core
- Package
- ArionUI.Core ·
dotnet add package ArionUI.Core --prerelease
Properties
CanRedo
bool CanRedo { get; }Is there an undone entry to re-apply?
CanUndo
bool CanUndo { get; }Is there an entry to revert? The enabled state of an undo button.
RedoDepth
int RedoDepth { get; }How many undone entries can be re-applied.
UndoDepth
int UndoDepth { get; }How many entries can be reverted. An application that writes "Undo (3)" into its menu, or shows the history as a list, needs the NUMBER — IUndoStack.CanUndo only ever says "more than none".
Methods
Clear
void Clear();Drop the whole history — e.g. after the app saved and replaced the items; stale references must not be replayed.
Record
void Record(Action undo, Action redo);Push an inverse-operation pair onto the history. The closures capture item IDENTITY, not indexes, so the entry survives sort/filter/group reshapes.
Redo
bool Redo();Re-apply the most recently undone entry. False when empty or refused.
Undo
bool Undo();Revert the most recent entry. False when empty or refused (read-only).
Events
HistoryChanged
event Action? HistoryChanged;Raised whenever IUndoStack.CanUndo/IUndoStack.CanRedo may have changed (record, undo, redo, clear, pruning). A bound button listens HERE instead of knowing which grid events happen to touch the history — that list is exactly what gets out of date.
