I\'m using a thir party code to manage undo/redo operations in a WindowsForm project.
I need to extend the Class to manage undo/redo operations in a Listview, this m
Try this approach: Forget this current implementation, start implementing your own Undo/Redo class.
Every Method that manipulates something needs to create it own Undo methods. Store the delegates and invoke it when required. I have make an example with a simple Add / Remove of listview items.
Public Class Form1
Dim _undoManager As New UndoManager
''' <summary>
''' Delegates to Remove an item
''' </summary>
''' <param name="rowNumber"></param>
''' <remarks></remarks>
Delegate Sub RemoveDelegate(item As Object)
''' <summary>
''' Delegates to Add an Item
''' </summary>
''' <param name="text"></param>
''' <remarks></remarks>
Delegate Sub AddDelegate(text As String)
Sub AddItem(name As String)
Dim newItem = ListView1.Items.Add(name)
'Crate an Undo Operation
Dim a As New action() With {.name = "Remove Item",
.Operation = New RemoveDelegate(AddressOf RemoveItem),
.data = New Object() {newItem}}
_undoManager.Undostack.Push(a)
' Create a Redo
Dim a As New action() With {.name = "Add Item",
.Operation = New AddDelegate(AddressOf AddItem),
.data = New Object() {name}}
_undoManager.Redostack.Push(a)
End Sub
Sub RemoveItem(item As Object)
ListView1.Items.Remove(item)
End Sub
''' <summary>
''' Changes the Text of the Item
''' </summary>
''' <param name="item"></param>
''' <param name="text"></param>
''' <remarks></remarks>
Sub changetext(item As Object, text As String)
Dim oldtext As String = item.text
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Me.AddItem("new Item")
End Sub
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
_undoManager.UndoLastAction()
End Sub
End Class
Class UndoManager
Public Property Undostack As New Stack(Of action)
Public Property Redostack As New Stack(Of action)
''' <summary>
''' Undos the top of the stack
''' </summary>
''' <remarks></remarks>
Sub UndoLastAction()
Dim action As action = Undostack.Pop ' Get the Action from Stack
action.Operation.DynamicInvoke(action.data) ' Invoke the reverse Action
End Sub
Sub RedoLastAction()
Dim action As action = Redostack.Peek' Get the Action from Stack, but dont remove
action.Operation.DynamicInvoke(action.data) ' Invoke the reverse Action
End Sub
End Class
Class action
''' <summary>
''' Name the Undo / Redo Action
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Property name As String
''' <summary>
''' Points to a method to excecute
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Property Operation As [Delegate]
''' <summary>
''' Data Array for the method to excecute
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Property data As Object()
End Class
If look closely at line 328, it already handles a ListView. Is it lacking in some way?
I see. It's a bit of how you define what a "Redo" should do. In your case you want to Redo an Undo operation. By default, a Redo repeats the last action. Even If you Undo something, the Redo Undos again. Try this approach: Understand the Code fragment only as building blocks. The "RemoveItem" Method don't add Code to Undo/Redo stack - Add this Undo Redo like in the Add - Method. If you don't need to 'Undo an Undo' - Operation, add a
Property IsDoingUndo as boolean
To UndoManager and set it true if doing an Undo. Check this Property in Add/Remove Method and don't add something to the Undo/Redo Stack. Like :
If not _UndoManager.IsDoingUndo then
...
else
...
endif
With this you will get control of what should be undo-able and redo-able. Sorry that I can not provide sourcecode this time.