Extend this Class to Undo/Redo in a Listview

后端 未结 3 1828
生来不讨喜
生来不讨喜 2021-01-05 01:59

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

相关标签:
3条回答
  • 2021-01-05 02:13

    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
    
    0 讨论(0)
  • 2021-01-05 02:29

    If look closely at line 328, it already handles a ListView. Is it lacking in some way?

    0 讨论(0)
  • 2021-01-05 02:29

    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.

    0 讨论(0)
提交回复
热议问题