【发布时间】:2013-11-14 10:42:20
【问题描述】:
我在尝试在 ListView 控件中实现撤消/重做操作时遇到太多问题,只是为了添加/删除项目。
我在此之前意识到 Extend this Class to Undo/Redo in a Listview 的一个相对问题,在那里我开始获得 50、100、200 和 300 点的多个赏金,总共 650 点......但没有人能真正帮助我在几周和几个月。
但是在那个问题经过一段时间后,最终用户 (@ThorstenC) 向我展示了一个可能的解决方案和一个好主意,他的代码不完整,所以他的代码是我想要实现/完成的。
问题是简单的“撤消”工作正常,但是当我尝试重做 1 次以上时,它会引发异常,因为它无法在列表视图中再次添加相同的项目,而且代码还有更多问题,例如在当我无法重做撤消操作或撤消重做操作时。
只是我需要帮助来为 Listview 项添加/删除创建一个有效的撤消/重做管理器,仅此而已,我已经编写了一半的代码,我需要帮助来完成它我对此一团糟.
这是我上传的 VS2012 中的一个简单 WinForms 源项目,用于测试撤消管理器失败:
http://elektrostudios.tk/UndoManager.zip
这是一个视频,向您展示我尝试撤消/重做的错误:http://www.youtube.com/watch?v=MAzChURATpM
这是@ThorstenC 的 UndoManager 类,稍作修饰:
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
【问题讨论】:
-
请缩短您的代码以表示相关部分。删除不必要的 cmets,请指出你的异常是在哪一行抛出的!
-
@Pilgerstorfer Franz 感谢您的评论,抱歉,代码和我的话不能少,因为我需要提供所有必要的信息,在这一行抛出异常:
_undoManager.RedoLastAction()you可以在我上传的视频中看到它,但这个异常并不是问题的全部,我会从我的问题中引用这个,请阅读:The problem is when I try to redo more than 1 time it throws an exception about it cant add the same item again in the listview, also the code has more problems for example ATM I'm not able to redo a undo operation, or undo a redo operation
标签: .net vb.net winforms listview undo-redo