So you have this two-level data structure in (or with) each GoDocument, but they are not GoObjects, and you want them to support undo/redo.
As an independent issue, this data structure reflects some of the GoObjects (nodes and links) in the GoDocument.
If I understood you correctly, you have already set up a GoDocument.Changed event handler (or overridden GoDocument.OnChanged) so that you can automatically update your data structures whenever any changes are made to the GoDocument, whether by user manipulation or by some code that modifies the document. And you have implemented your data structures so that if you make any direct changes to them, you also make any appropriate changes to (including creating and removing) the corresponding GoObjects in the document.
It sounds like the easiest thing is to integrate into the existing GoUndoManager by calling GoDocument.RaiseChanged with some new Hint values that you define, as you make changes to your data structures, including adding, removing, and modifying. You will also need to override GoDocument.ChangeValue to handle those new hints, so that when an undo or a redo occurs, you use the information in the GoChangedEventArgs to recover/restore the desired state.
In the samples there are several examples of implementing undo/redo managed state in subclasses of GoDocument. I think all of the examples just implement simple property values, not collections like what you have, but you can check.
The UpdateDemo sample just implements the two-way updating of the document and the internal data structures. I don’t think it implements additional Hints to allow state to be undo/redo managed independently of any GoObjects.
Oh, just to reinforce the message – GoDiagram’s undo/redo architecture is completely extensible, and I believe GoDiagram uses this mechanism to implement undo/redo in exactly the same manner that you can for your own classes and state.
In other words, I believe our internal support for undo/redo only uses the publically accessible mechanisms of GoUndoManager and IGoUndoableEdit.
But you too can make use of the predefined mechanisms that GoDocument and GoChangedEventArgs provide, just to make your programming easier. That’s what I’m recommending in my previous post.
Your block and task objects are not GoObjects, right? They are your own independent classes that are associated with (belong to?) a GoDocument?
(If they were GoObjects, and in particular if task were a GoGroup, then you wouldn’t need to do anything to get undo/redo support.)
I don’t understand why your Form1 is being Dispose’d.
GoObject.OnLayerChanged is always called when the GoObject.Layer property changes. GoDocument.RaiseChanged is also called when the GoObject.Layer changes. The order in which they are called depends on whether it’s being added to a layer or being removed from it. (Also, GoDocument.Changed event handlers are not called when GoDocument.SuspendsUpdates is true, but that should never be the case for you.)
Actually, those are the nodes extending GoMultiTextNode. And, yes, they belong to a document, like in it’s layers, but also as a custom structure for easier programming and understanding the code. But I still do need to fix the undo / redo support, because the only thing supported is getting them back to the layers / document. Upon undo, they do become a part of a GoDocument and visible, but they don’t become a part of the structure they were deleted from. Maybe the reason for that is in the fact that I have used GoMultiTextNode’s OnLayerChanged instead of GoDocument’s OnChanged?
Well, undo/redo of adding and removing of GoObject from GoGroups is already supported by GoDiagram, so you don’t need to do anything there.
Are you saying you have additional collections that you need to maintain? Like an extra list in each Task, that holds some number of Blocks?
If so, then each time you add a Block to a Task you call RaiseChanged with your new Hint value, passing the needed information such as the Task, the added Block, and maybe the index of the Block in the Task’s list (if that matters). Same goes for removing a Block from a Task. Note that the reason there are so many arguments to GoDocument.RaiseChanged, and also that there are so many properties in GoChangedEventArgs, is so that you can easily pass all the information you need to be able to undo or to redo that modification.
In any case it doesn’t sound like you care about whether a Block is added to or removed from a layer, but whether it is added to or removed from a Task. So overriding OnLayerChanged is probably the wrong event to check for.