Implementieren Sie Undo / Redo-Vorgänge zum Hinzufügen / Löschen von ListView-Elementen

Ich habe zu viele Probleme beim Versuch, eine Undo / Redo-Operation in einem ListView-Steuerelement zu implementieren, nur um Elemente hinzuzufügen / zu entfernen.

Ich habe vor einiger Zeit eine relative Frage hier festgestelltErweitern Sie diese Klasse in einer Listenansicht auf Rückgängig / Wiederherstellen Wo ich angefangen habe mehrere Kopfgelder von 50, 100, 200 und 300 Punkten, insgesamt 650 Punkte ... aber niemand konnte mir wirklich helfen, dieses Problem in Wochen und Monaten abzuschließen.

Aber nach einiger Zeit in dieser Frage zeigte mir endlich ein Benutzer (@ThorstenC) eine mögliche Lösung und eine großartige Idee, der Code von ihm ist unvollständig, so dass der Code von ihm das ist, was ich zu realisieren / zu beenden versuche.

Das Problem ist, dass einfaches "Rückgängigmachen" gut funktioniert, aber wenn ich mehr als ein Mal versuche, eine Ausnahme auszulösen, kann das gleiche Element nicht erneut in die Listenansicht eingefügt werden. Außerdem hat der Code im Moment zum Beispiel mehr Probleme Ich kann einen Vorgang nicht rückgängig machen oder einen Vorgang rückgängig machen.

Ich brauche nur Hilfe, um einen funktionierenden Undo / Redo-Manager für das Hinzufügen / Entfernen von Listview-Elementen zu erstellen. Das ist alles. Ich habe den halben Teil des Codes geschrieben. Ich brauche Hilfe, um ihn zu beenden. Ich habe ein Durcheinander in meinem Kopf.

Hier ist ein einfaches WinForms-Quellprojekt in VS2012, das ich zum Testen des Undo-Managers hochgeladen habe:

http://elektrostudios.tk/UndoManager.zip

Hier ist ein Video, in dem die Fehler gezeigt werden, die beim Rückgängigmachen / Wiederherstellen auftreten:http://www.youtube.com/watch?v=MAzChURATpM

Hier ist die UndoManager-Klasse von @ThorstenC mit ein paar Retuschen:

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

Und hier ist der Rest des Codes, in dem ich versuche, das Hinzufügen / Löschen von Listenansichtselementen rückgängig zu machen / zu wiederholen:

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

Antworten auf die Frage(2)

Ihre Antwort auf die Frage