You will have to create an undo stack. Populate this stack after each editing action on the data table with enough info to undo it. Then provide a mechanism to perform the actions in the stack in reverse manner.
say, you have two columns in your table, int c1 and varchar c2. Just to hint you, here are some sample classes.
struct ColData{
int c1;
string c2;
};
class Action {
public abstract bool Undo(){}
public abstract bool Redo(){}
}
class AddAction : Action{
ColData data;
public AddAction(ColData d){data = d;}
public override bool Undo(){
//remove the row
//identify it with info from local field 'data'
}
public override bool Redo(){
//add the row with info from local field 'data'
}
}
//other actions like Delete, Update
And so on for all other actions. For editing actions you may need two sets of column values: old and new, so that you could repeat the change back and forth.
Each time you have a change, you push a corresponding Action onto the action stack. When asked to undo, you pop it out of undo stack, call it's Undo method, and push it onto the redo stack. If you are asked to redo some action, you pop from redo stack, call Redo, push to undo stack.
When you have another new action you should clear you redo stack and push the new action to the undo stack.