好吧,我在这里谈谈这个问题的第二部分,Implement Undo/Redo operations for Add/Deleting ListView Items和另一个Extend this Class to Undo/Redo in a Listview。
我正在尝试为添加/删除 ListView 项实现撤消/重做操作。
我在这个 LV UndoManager 代码的编码方面已经进步了一点,但是当我尝试进步时,这对我来说总是很困难。
目前我可以添加单个项目,然后我可以完美地撤消/重做添加的项目,仅此而已。
我遇到的问题是:
·当我从列表视图中删除单个项目时,我无法执行“撤消”以再次将删除的项目添加到 LV 中。
·当我添加一个范围,如果我无法撤消的项目,当我调用UndoLastAction
它时会抛出System.Reflection.TargetParameterCountException
异常
·当我删除一系列项目时,我无法撤消/重做操作并启动相同的异常。
在简历中,如果我添加一个项目,我可以完美地撤消/重做,如果我删除一个项目,我无法正确撤消,我也无法撤消/重做一系列 ListViewItem。
我需要有人能耐心地帮助我解决这些问题……或者至少其中一个问题。
代码有点大,所以我认为可能需要更少的时间来理解和发现打开和测试我上传的这个源项目的错误。
这是full
来源:
http://elektrostudios.tk/UndoManager%20Test%20Application.zip
只是一张图片:
这是 UndoManager 类:
Class ListView_UndoManager
Private action As ListView_Action = Nothing
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
''' <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.
End Sub
''' <summary>
''' Redo the last action.
''' </summary>
''' <remarks></remarks>
Sub RedoLastAction()
If Redostack.Count = 0 Then Exit Sub ' Nothing to Redo.
action = Redostack.Pop() ' Get the Action from Stack and remove it.
action.Operation.DynamicInvoke(action.data) ' Invoke the redo Action.
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 ListViewItem()
End Class
这是我正在使用的 ListView 用户控件,我发布这个是因为我正在触发的事件很重要:ItemAdded
、ItemRemoved
和。RangeItemAdded
RangeItemRemoved
Public Class LV : Inherits ListView
Public Shared Event ItemAdded As EventHandler(Of ItemAddedEventArgs)
Public Class ItemAddedEventArgs : Inherits EventArgs
Public Property Item As ListViewItem
End Class
Public Shared Event ItemRemoved As EventHandler(Of ItemRemovedEventArgs)
Public Class ItemRemovedEventArgs : Inherits EventArgs
Public Property Item As ListViewItem
End Class
Public Shared Event RangeItemAdded As EventHandler(Of RangeItemAddedEventArgs)
Public Class RangeItemAddedEventArgs : Inherits EventArgs
Public Property Items As ListViewItem()
End Class
Public Shared Event RangeItemRemoved As EventHandler(Of RangeItemRemovedEventArgs)
Public Class RangeItemRemovedEventArgs : Inherits EventArgs
Public Property Items As ListViewItem()
End Class
Public Sub New()
Me.Name = "ListView_Elektro"
Me.GridLines = True
Me.FullRowSelect = True
Me.MultiSelect = True
Me.View = View.Details
End Sub
''' <summary>
''' Adds an Item to the ListView,
''' to monitor when an Item is added to the ListView.
''' </summary>
Public Function AddItem(ByVal Item As ListViewItem) As ListViewItem
RaiseEvent ItemAdded(Me, New ItemAddedEventArgs With { _
.Item = Item
})
Return MyBase.Items.Add(Item)
End Function
''' <summary>
''' Adds a range of Items to the ListView,
''' to monitor when an Item is added to the ListView.
''' </summary>
Public Sub AddItem_Range(ByVal Items As ListViewItem())
RaiseEvent RangeItemAdded(Me, New RangeItemAddedEventArgs With { _
.Items = Items
})
MyBase.Items.AddRange(Items)
End Sub
''' <summary>
''' Removes an Item from the ListView
''' to monitor when an Item is removed from the ListView.
''' </summary>
Public Sub RemoveItem(ByVal Item As ListViewItem)
RaiseEvent ItemRemoved(Me, New ItemRemovedEventArgs With { _
.Item = Item
})
MyBase.Items.Remove(Item)
End Sub
''' <summary>
''' Removes a range of Items from the ListView
''' to monitor when an Item is removed from the ListView.
''' </summary>
Public Sub RemoveItem_Range(ByVal Items As ListViewItem())
RaiseEvent RangeItemRemoved(Me, New RangeItemRemovedEventArgs With { _
.Items = Items
})
For Each Item As ListViewItem In Items
MyBase.Items.Remove(Item)
Next
End Sub
End Class
最后是测试应用程序的 Form1 代码,这里是我用来添加/删除项目和调用撤消/重做的东西,但我调用了我的自定义 ListView 用户控件的方法,所以你需要注意... :
Public Class Form1
Dim _undoManager As New ListView_UndoManager
Dim LVItem As ListViewItem
Delegate Sub AddDelegate(item As ListViewItem)
Delegate Sub RemoveDelegate(item As ListViewItem)
Delegate Sub AddRangeDelegate(item As ListViewItem())
Delegate Sub RemoveRangeDelegate(item As ListViewItem())
' Adds a single item
Private Sub Button_AddItem_Click(sender As Object, e As EventArgs) _
Handles Button_AddItem.Click
Dim index As String = CStr(LV1.Items.Count + 1)
LVItem = New ListViewItem With {.Text = index}
LVItem.SubItems.AddRange({"Hello " & index, "World " & index})
LV1.AddItem(LVItem)
End Sub
' Adds a range of 2 items to the ListView
Private Sub Button_AddRange_Of_Items_Click(sender As Object, e As EventArgs) Handles Button_AddRange_Of_Items.Click
Dim index As String = CStr(LV1.Items.Count + 1)
Dim lvitem As New ListViewItem With {.Text = index}
lvitem.SubItems.AddRange({"Hello " & index, "World " & index})
Dim lvitem2 As New ListViewItem With {.Text = index + 1}
lvitem2.SubItems.AddRange({"Hello " & index + 1, "World " & index + 1})
LV1.AddItem_Range({lvitem, lvitem2})
End Sub
' Removes the last item
Private Sub Button_RemoveLastItem_Click(sender As Object, e As EventArgs) _
Handles Button_RemoveLastItem.Click
If LV1.Items.Count <> 0 Then
LV1.RemoveItem(LV1.Items.Cast(Of ListViewItem).Last)
End If
End Sub
' Clear all items
Private Sub Button_Clear_Items_Click(sender As Object, e As EventArgs) _
Handles Button_Clear_Items.Click
LV1.Items.Clear()
End Sub
' Clear the Undo/Redo Stacks
Private Sub Button_Clear_Stacks_Click(sender As Object, e As EventArgs) _
Handles Button_Clear_Stacks.Click
_undoManager.Undostack = New Stack(Of ListView_Action)
_undoManager.Redostack = New Stack(Of ListView_Action)
Label_UndoCount_Value.Text = CStr(0)
Label_RedoCount_Value.Text = CStr(0)
End Sub
' Refreshes the Stacks Count
Private Sub Refresh_StackCount()
Label_UndoCount_Value.Text = CStr(_undoManager.Undostack.Count)
Label_RedoCount_Value.Text = CStr(_undoManager.Redostack.Count)
End Sub
' Monitors when an Item is added
Private Sub ListView_ItemAdded(sender As Object, e As LV.ItemAddedEventArgs) _
Handles LV1.ItemAdded
' // Crate an Undo Action
Dim u As New ListView_Action()
With u
.name = "Remove Item"
.Operation = New RemoveDelegate(AddressOf LV1.RemoveItem)
.data = {e.Item}
End With
_undoManager.Undostack.Push(u)
Refresh_StackCount()
End Sub
' Monitors when a range of Items are added
Private Sub ListView_RangeItemAdded(sender As Object, e As LV.RangeItemAddedEventArgs) _
Handles LV1.RangeItemAdded
' // Crate an Undo Action
Dim u As New ListView_Action()
With u
.name = "Remove Item Range"
.Operation = New RemoveRangeDelegate(AddressOf LV1.RemoveItem_Range)
.data = e.Items
End With
_undoManager.Undostack.Push(u)
Refresh_StackCount()
End Sub
' Monitors when an Item is removed
Private Sub ListView_ItemRemoved(sender As Object, e As LV.ItemRemovedEventArgs) _
Handles LV1.ItemRemoved
' // Create a Redo Action
Dim r As New ListView_Action()
With r
.name = "Add Item"
.Operation = New AddDelegate(AddressOf LV1.AddItem)
.data = {e.Item}
End With
_undoManager.Redostack.Push(r)
Refresh_StackCount()
End Sub
' Monitors when a range of Items are removed
Private Sub ListView_RangeItemRemoved(sender As Object, e As LV.RangeItemRemovedEventArgs) _
Handles LV1.RangeItemRemoved
' // Create a Redo Action
Dim r As New ListView_Action()
With r
.name = "Add Item"
.Operation = New AddRangeDelegate(AddressOf LV1.AddItem_Range)
.data = e.Items
End With
_undoManager.Redostack.Push(r)
Refresh_StackCount()
End Sub
' Undo
Private Sub Button_Undo_Click(sender As Object, e As EventArgs) _
Handles Button_Undo.Click
_undoManager.UndoLastAction()
End Sub
' Redo
Private Sub Button_Redo_Click(sender As Object, e As EventArgs) _
Handles Button_Redo.Click
_undoManager.RedoLastAction()
End Sub
Private Sub Button_Remove_Range_Of_Items_Click(sender As Object, e As EventArgs) Handles Button_Remove_Range_Of_Items.Click
If LV1.Items.Count > 1 Then
Dim lvi1 As ListViewItem = LV1.Items(LV1.Items.Count - 1)
Dim lvi2 As ListViewItem = LV1.Items(LV1.Items.Count - 2)
LV1.RemoveItem_Range({lvi1, lvi2})
End If
End Sub
End Class
PS:就像我说的那样,下载源并测试它真的会更友好。