Реализуйте операции отмены / возврата для добавления / удаления элементов ListView

У меня слишком много проблем, когда я пытаюсь реализовать операцию Undo / Redo в элементе управления ListView, просто чтобы добавить / удалить элементы.

Я понял, что время назад относительный вопрос здесьРасширить этот класс, чтобы отменить / повторить в ListView где я начал многократные награды в 50, 100, 200 и 300 баллов, в общей сложности 650 баллов ... но никто не мог реально помочь мне решить эту проблему за недели и месяцы.

Но спустя время в этом вопросе, наконец, пользователь (@ThorstenC) показал мне возможное решение и отличную идею, его код неполон, поэтому его код - это то, что я пытаюсь реализовать / закончить.

Проблема в том, что просто «отменить» работает нормально, но когда я пытаюсь повторить более 1 раза, выдается исключение о том, что он не может добавить один и тот же элемент снова в просмотр списка, также код имеет больше проблем, например, в данный момент я Я не могу отменить операцию отмены или отменить операцию возврата.

Просто мне нужна помощь, чтобы сделать работающий менеджер Undo / Redo для добавления / удаления элемента Listview, вот и все, я написал половину кода, мне нужна помощь, чтобы закончить, у меня в голове беспорядок с этим.

Вот простой исходный проект WinForms в VS2012, который я загрузил, чтобы протестировать диспетчер отмены:

http://elektrostudios.tk/UndoManager.zip

Вот видео, чтобы показать вам ошибки, которые я получаю, пытаясь отменить / повторить:http://www.youtube.com/watch?v=MAzChURATpM

Вот класс UndoManager @ThorstenC с небольшими ретушами:

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

А вот остальная часть кода, в котором я пытаюсь отменить / повторить добавление / удаление элементов списка:

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

Ответы на вопрос(2)

Ваш ответ на вопрос