Implementar operaciones de deshacer / rehacer para agregar / eliminar elementos de ListView

Tengo demasiados problemas al intentar implementar una operación de Deshacer / Rehacer en un Control ListView, solo para agregar / eliminar elementos.

Me di cuenta hace tiempo una pregunta relativa aquí.Extienda esta clase para deshacer / rehacer en una vista de lista donde comencé múltiples recompensas de 50, 100, 200 y 300 puntos, un total de 650 puntos ... pero ningún cuerpo realmente me ayudó a finalizar este problema en semanas y meses.

Pero luego de un tiempo en esa pregunta, finalmente un usuario (@ThorstenC) me mostró una posible solución y una gran idea, el código de él está incompleto, por lo que el código de él es lo que estoy intentando realizar / terminar.

El problema es que el simple "deshacer" funciona bien, pero cuando intento rehacer más de una vez, se produce una excepción al respecto, ya que no puedo agregar el mismo elemento en la vista de lista, también el código tiene más problemas, por ejemplo, en este momento. No puedo rehacer una operación de deshacer, o deshacer una operación de rehacer.

Solo necesito ayuda para hacer que un administrador de Deshacer / Rehacer funcione para agregar / eliminar un elemento de Listview, eso es todo, he escrito la mitad del código, necesito ayuda para terminarlo. Tengo un lío en mi cabeza con esto.

Aquí hay un proyecto fuente de WinForms simple en VS2012 que he cargado para probar que el administrador de deshacer falla:

http://elektrostudios.tk/UndoManager.zip

Aquí hay un video para mostrarte los errores que obtengo al intentar deshacer / rehacer:http://www.youtube.com/watch?v=MAzChURATpM

Aquí está la clase UndoManager de @ThorstenC con algunos pequeños retoques:

Class ListView_UndoManager

    Public Property Undostack As New Stack(Of ListView_Action)
    Public Property Redostack As New Stack(Of ListView_Action)

    Public Property IsDoingUndo As Boolean ' = False
    Public Property IsDoingRedo As Boolean ' = False

    Private action As ListView_Action = Nothing

    ''' <summary>
    ''' Undo the last action.
    ''' </summary>
    ''' <remarks></remarks>
    Sub UndoLastAction()

        If Undostack.Count = 0 Then Exit Sub ' Nothing to Undo.

        action = Undostack.Pop ' Get the Action from Stack and remove it.
        action.Operation.DynamicInvoke(action.data) ' Invoke the undo Action.

        'Redostack = New Stack(Of ListView_Action)(Redostack)
        'Redostack.Pop()
        'Redostack = New Stack(Of ListView_Action)(Redostack)

    End Sub

    ''' <summary>
    ''' Redo the last action.
    ''' </summary>
    ''' <remarks></remarks>
    Sub RedoLastAction()

        ' If Redostack.Count = Undostack.Count Then Exit Sub

        If Redostack.Count = 0 Then Exit Sub ' Nothing to Redo.

        'Redostack = New Stack(Of ListView_Action)(Redostack) ' Reverse the Stack contents.

        action = Redostack.Pop() ' Get the Action from Stack and remove it.
        ' action = Redostack.Peek()

         action.Operation.DynamicInvoke(action.data) ' Invoke the redo Action.

        'Redostack = New Stack(Of ListView_Action)(Redostack) ' Re-Reverse the Stack contents.

    End Sub

End Class

Class ListView_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

Y aquí está el resto del código donde estoy tratando de deshacer / rehacer Agregar / Borrar elementos de vista de lista:

Public Class Form1


    Dim _undoManager As New ListView_UndoManager
    Delegate Sub RemoveDelegate(item As ListViewItem)
    Delegate Sub AddDelegate(item As ListViewItem)

    Dim newItem As ListViewItem = Nothing



    Sub AddItem(ByVal item As ListViewItem)

        ' // Crate an Undo Action
        Dim u As New ListView_Action() With {.name = "Remove Item",
                            .Operation = New RemoveDelegate(AddressOf RemoveItem),
                                    .data = New Object() {newItem}}

        _undoManager.Undostack.Push(u)

        ListView_Elektro1.AddItem(item)

    End Sub

    Sub RemoveItem(item As ListViewItem)

        ' // Create a Redo Action
        Dim r As New ListView_Action() With {.name = "Add Item",
                    .Operation = New AddDelegate(AddressOf AddItem),
                            .data = New Object() {item}}

        _undoManager.Redostack.Push(r)

        ' Remove the ListViewItem from ListView
        ListView_Elektro1.RemoveItem(item)

    End Sub

    Private Sub Button_AddItem_Click(sender As Object, e As EventArgs) _
    Handles Button_AddItem.Click

        Dim index As String = CStr(ListView_Elektro1.Items.Count + 1)

        newItem = New ListViewItem _
                  With {.Text = index}
        newItem.SubItems.AddRange({"Hello " & index, "World " & index})

        AddItem(newItem)

    End Sub

    Private Sub Button_RemoveItem_Click(sender As Object, e As EventArgs) _
    Handles Button_RemoveItem.Click

        newItem = ListView_Elektro1.Items.Cast(Of ListViewItem).Last

        RemoveItem(newItem)

    End Sub

    Private Sub Button_Undo_Click(sender As Object, e As EventArgs) _
    Handles Button_Undo.Click

        ' _undoManager.IsDoingUndo = True
        _undoManager.UndoLastAction()
        ' _undoManager.IsDoingUndo = False

    End Sub

    Private Sub Button_Redo_Click(sender As Object, e As EventArgs) _
    Handles Button_Redo.Click

        '_undoManager.IsDoingRedo = True
        _undoManager.RedoLastAction()
        '_undoManager.IsDoingRedo = False

    End Sub

    Private Sub ListView_Elektro1_ItemAdded() _
    Handles ListView_Elektro1.ItemAdded, _
            ListView_Elektro1.ItemRemoved

        Label_UndoCount_Value.Text = CStr(_undoManager.Undostack.Count)
        Label_RedoCount_Value.Text = CStr(_undoManager.Redostack.Count)

    End Sub

End Class

Respuestas a la pregunta(2)

Su respuesta a la pregunta