Undo Redo in Windows Forms Grid Control
8 Aug 20238 minutes to read
GridControl gives support for Undo/Redo functionality. GridControl keeps a track on all the operations undergone, in a particular class GridModelCommandManager. The Undo/Redo operations can be done by using commands, methods and keyboard shortcuts.
Basic Commands
GridControl has GridModelCommandManager class that implements support for the Undo/Redo commands in a grid. If an operation in a GridControl is done then the changes made will get tracked and stored in stack structures which will be stored in this class.
GridControl has a property CommandStack which will return a reference to GridModelCommandManager. Undo/Redo operations can be enabled/disabled through this property.
// Turns on Undo/Redo buffer
this.gridControl1.CommandStack.Enabled = true;
// Turns off Undo/Redo buffer
this.gridControl1.CommandStack.Enabled = false;
' Turns on Undo/Redo buffer
Me.gridControl1.CommandStack.Enabled = True
' Turns off Undo/Redo buffer
Me.gridControl1.CommandStack.Enabled = False
Undo
The undo operation can be done in GridControl by using the CommandStack.Undo method. By default, GridControl also give support for undoing the actions using keyboard shortcuts. Use Ctrl+Z combination for Undo operation to happen.
// Makes the undo operation
this.gridControl1.CommandStack.Undo();
// Clears the Undo buffer
this.gridControl1.CommandStack.Undo.Clear();
' Makes the undo operation
Me.gridControl1.CommandStack.Undo()
' Clears the Undo buffer
Me.gridControl1.CommandStack.Undo.Clear()
Redo
The redo operation can be done by using the CommandStack.Redo method. Ctrl+Y combination is the keyboard shortcut for the redoing process.
// Makes the redo operation
this.gridControl1.CommandStack.Redo();
// Clears the Undo buffer
this.gridControl1.CommandStack.Redo.Clear();
' Makes the redo operation
Me.gridControl1.CommandStack.Redo()
' Clears the Undo buffer
Me.gridControl1.CommandStack.Redo.Clear()
Transactions
A Transaction is a series of steps that will be treated as a single action in the Undo/Redo architecture. For example, if a list of operations has been done and undoing these operations in a single click or way is known as Transaction.
Transaction can be done by using the methods BeginTrans, CommitTrans and RollBack in the GridModelCommandManager
class.
BeginTrans
A call to CommandStack.BeginTrans will mark the start of a series of actions that are to be treated as a single Undo/Redo step. Once BeginTrans
is called, all the changes are marked as being a member of a single transaction until either CommitTrans
or RollBack
is called.
// Transaction will be started
this.gridControl1.CommandStack.BeginTrans("Transaction started");
After starting the transaction using the above method, do the list of changes in grid so that it will stored as one transaction while committing the transaction using CommitTrans
method.
CommitTrans
CommandStack.CommitTrans method will denote the GridControl to stop the transaction and to save all the changes in one transaction. Then this single transaction will be stored in stack.
// Current Transaction will be stopped
this.gridControl1.CommandStack.CommitTrans();
' Current Transaction will be stopped
Me.gridControl1.CommandStack.CommitTrans()
Rollback
A call to CommandStack.Rollback method will cause all the changes in the current transaction to be undone and will end the transaction processing. Rollback call will return the grid to the same state that it was immediately prior to the call to BeginTrans.
// Current Transaction will be stopped and undone
this.gridControl1.CommandStack.Rollback();
' Current Transaction will be stopped and undone
Me.gridControl1.CommandStack.Rollback()
Custom Commands
Undo/Redo methods can be handled manually and not the standard implementation used in Undo/Redo architecture, by using the derived custom commands from the GridModelCommand abstract class. In the derived class, add necessary members to track the Undo/Redo actions.
public class MyCustomCommand : GridModelCommand
{
// Constructor for MyCustomCommand class.
public MyCustomCommand()
{
}
// Overrides the Execute method.
public override void Execute()
{
}
}
Public Class MyCustomCommand
Inherits GridModelCommand
'Constructor for MyCustomCommand class.
Public Sub New()
End Sub
'Overrides the Execute method.
Public Overrides Sub Execute()
End Sub
End Class
After creating the GridModelCommand
derived class, create a proper instance of your derived GridModelCommand
class and add it to CommandStack.UndoStack whenever the action is taken.
Creating Custom Commands for Covered Cells
To create a custom command on making the undo/redo operations for covered ranges cells, make use of the below code which explains a simple way on achieving it.
The GridModelCommand
class has an overridden method called Execute. This method will execute the set of codes mentioned in it while the custom undo/redo process goes on.
public class GridModelSetCoveredRangesCommand
: GridModelCommand
{
GridRangeInfoList ranges;
bool setOrReset;
private GridModelCoveredRanges coveredRange;
public GridModelSetCoveredRangesCommand(GridModelCoveredRanges coveredRange, GridRangeInfoList ranges, bool setOrReset)
: base(coveredRange.Model)
{
if (setOrReset)
{
SetDescription("CommandAddCoveredRanges");
}
else
{
SetDescription("CommandRemoveCoveredRanges");
}
this.coveredRange = coveredRange;
this.ranges = ranges;
this.setOrReset = setOrReset;
}
// Executes the command.
public override void Execute()
{
coveredRange.SetCoveredRanges(ranges, setOrReset);
Grid.ScrollCellInView(ranges.ActiveRange, GridScrollCurrentCellReason.Command);
}
}
Public Class GridModelSetCoveredRangesCommand
Inherits GridModelCommand
Private ranges As GridRangeInfoList
Private setOrReset As Boolean
Private coveredRange As GridModelCoveredRanges
Public Sub New(ByVal coveredRange As GridModelCoveredRanges, ByVal ranges As GridRangeInfoList, ByVal setOrReset As Boolean)
MyBase.New(coveredRange.Model)
If setOrReset Then
SetDescription("CommandAddCoveredRanges")
Else
SetDescription("CommandRemoveCoveredRanges")
End If
Me.coveredRange = coveredRange
Me.ranges = ranges
Me.setOrReset = setOrReset
End Sub
' Executes the command.
Public Overrides Sub Execute()
coveredRange.SetCoveredRanges(ranges, setOrReset)
Grid.ScrollCellInView(ranges.ActiveRange, GridScrollCurrentCellReason.Command)
End Sub
End Class
After creating the class, add the transaction to the GridControl by using the CommandStack.Push method. Call this method to necessary places in which the users need to make the Undo/Redo operations.
this.gridControl1.CommandStack.Push(new GridModelSetCoveredRangesCommand(this.gridControl1.Model.CoveredRanges, list, false));
After pushing the custom command unto the stack, if user make any merge cells using the covered ranges then it can be undone by using the Undo method or by keyboard shortcuts.