实现添加/删除 ListView 项目的撤消/重做操作

2023-11-29

我在尝试在 ListView 控件中实现撤消/重做操作时遇到太多问题,只是为了添加/删除项目。

我不久前意识到这里有一个相关问题扩展此类以在列表视图中撤消/重做我开始获得 50、100、200 和 300 点的多重赏金,总共 650 点……但没有人能真正帮助我在几周和几个月内完成这个问题。

但是在这个问题之后,终于有一个用户(@ThorstenC)向我展示了一个可能的解决方案和一个好主意,他的代码不完整,所以他的代码就是我想要实现/完成的。

问题是简单的“撤消”工作正常,但是当我尝试重做超过 1 次时,它会抛出一个异常,关于它无法在列表视图中再次添加相同的项目,而且代码还有更多问题,例如目前我无法重做撤消操作,或撤消重做操作。

只是我需要帮助来为 Listview 项目添加/删除创建一个工作撤消/重做管理器,仅此而已,我已经编写了一半的代码,我需要帮助来完成它,我对此一团糟。

这是 VS2012 中的一个简单的 WinForms 源项目,我已上传该项目来测试撤消管理器失败:

http://elektrostudios.tk/UndoManager.zip

enter image description here

这是一个视频,向您展示我尝试撤消/重做的错误: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

“El URL requerido no fue encontrado en este servidor。”所以我很确定就是这样:

action = Redostack.Peek() ' Get the Action from Stack and remove it.

不,你正在看它without从堆栈中获取它。我确实使用了原始版本和快速修改版:

action = Redostack.Pop() 

由于您将实际的 LV 项目存储在堆栈中以回传到 LV,因此当您第二次按下它时,您将查看并尝试恢复 LV 中已有的项目。

由于大多数原始“命令”将撤消/重做数据保存为对象,为什么您不直接公开一个AddLVUndoItem(item)在 UnDoReDoManager 上使用现有代码将 LV 操作与其他控件集成?它的问题是没有 LVItemAdded 事件来自动抓取这些东西。将此功能与另一个功能一起用作用户控制功能的一个问题是,您现在有 2 个堆栈,其中一个跳过 LV,另一个仅跳过 LV。用户可以清空另一个堆栈来尝试进行 LV 撤消操作。

此外,添加项目会落入 UnDo 存储桶中,但不会落入 RemoveItem 中,反之亦然(无法 Undo RemoveItem)。原来Undo中自动将命令添加到ReDo堆栈中。它位于标题和旧请求中,但不在代码中。

Edit这是错误的:

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}}   ' wrong!

    _undoManager.Redostack.Push(r)

    ' Remove the ListViewItem from ListView
    ListView_Elektro1.RemoveItem(item)
End Sub

您不必为 undoStack 创建新的 LVI,而是使用传递的 LVI 和删除的 LVI(回想一下,我必须更改 VS 版本的语法):

Sub RemoveItem(ByVal item As ListViewItem)

    ' // Create a Redo Action
    Dim r As New ListView_Action()
    With r
        .name = "Add Item"
        .Operation = New AddDelegate(AddressOf AddItem)
        .data = item           ' use the one passed!!!
    End With

    _undoManager.Redostack.Push(r)

    ' Remove the ListViewItem from ListView
    LVE.RemoveItem(item)
    _undoManager.ShowStacks()

End Sub

因此,您的重做不会缓存任何撤消操作。看起来只是由于人工测试数据造成的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

实现添加/删除 ListView 项目的撤消/重做操作 的相关文章

  • 如何将行从一个 DataGridView 移动到另一个 DataGridView?

    我有两个具有相同列架构的 DataGridView 尽管两个不同的 DataView 作为数据源 如果这很重要 将行从一个数据网格视图移动到另一个数据网格视图的最佳 最快方法是什么 我相信如果您在 DataTable table1 中有一行
  • 如何获取可用系统内存的大小?

    C NET 中是否可以获取系统可用内存的大小 如果是的话怎么办 Use Microsoft VisualBasic Devices ComputerInfo TotalPhysicalMemory http msdn microsoft c
  • .NET 内存不足故障排除

    在阅读了几篇有关 NET 技术中的内存的启发性文章后 Out of Memory 不是指物理内存 https learn microsoft com en us archive blogs ericlippert out of memory
  • 注销租约抛出 InvalidOperationException

    我有一个使用插件的应用程序 我在另一个应用程序域中加载插件 我使用 RemoteHandle 类http www pocketsilicon com post Things That Make My Life Hell Part 1 App
  • 如何在 32 位或 64 位配置中以编程方式运行任何 CPU .NET 可执行文件?

    我有一个可在 32 位和 64 位处理器上运行的 C 应用程序 我试图枚举给定系统上所有进程的模块 当尝试从 64 位应用程序枚举 32 位进程模块时 这会出现问题 Windows 或 NET 禁止它 我认为如果我可以从应用程序内部重新启动
  • 函数的变量存储在哪里?在堆栈或堆上?

    当程序调用函数时 为该函数中的变量分配哪种类型的数据结构内存 堆还是栈 为什么 在我看来 它应该存储在堆栈上 因为它们不一定是引用类型 但在我读到答案的地方 据说它们存储在堆上 并在函数返回值后释放 它比这更复杂一点 事实上使用堆栈和堆实际
  • 如何使用 Entity Framework 4.1 Fluent API 映射 Enum?

    我在 EF 的工作表之间有些迷失了 就像自由世界的其他部分一样 我确实需要在我的 POCO 中使用枚举 像我交谈过的许多人一样 我非常喜欢使用代码映射枚举 只是因为 我只是不太喜欢图片 我的困境是 我在几乎每一篇文章中都得到了相互矛盾的信息
  • 空 catch 与 try-catch 语句中的“catch Exception”相同吗?

    try catch Exception 我可以写吗 try catch 这在 C NET 3 5 中可以吗 代码看起来更好 但我不知道是否相同 他们是not一样的 catch Exception 将仅捕获托管异常 catch 也会捕获非 C
  • 如何将位写入文件?

    如何使用 c net 将位 而不是字节 写入文件 我很坚持它 Edit 我正在寻找一种不同的方法 将每 8 位写为一个字节 一次可以写入的最小数据量是一个字节 如果您需要写入单独的位值 例如 二进制格式需要 1 位标志 3 位整数和 4 位
  • 如何在目录中查找或获取文件名 Visual Basic.net 中具有特定单词的文件?

    我需要从名称中包含特定字符的目录中获取文件 下面的代码将返回带有以下内容的任何文件 csv扩大 问题是还有其他 csv 文件我需要保留或得不到 Dim FileLocation As DirectoryInfo New DirectoryI
  • 类库的 app.config 中的绑定重定向有什么作用吗?

    我经常使用的 VS 解决方案包括单个可执行项目 控制台应用程序 网络应用程序 和许多类库项目这些都被可执行文件引用 使用 NuGet 并安装包时 经常会出现app config为每个项目创建的文件 通常只包含合并引用程序集版本的绑定重定向列
  • 将寻呼机视为列表视图行项目

    我有一个包含 20 行的列表视图 我想为列表视图中的每一行设置一个视图寻呼机 由于列表视图的行中的项目可能是一个或多个 并且我想使用视图分页器显示列表视图行项目 为此 我使用以下代码 将显示在列表视图行中的自定义布局 作为分页器项目
  • Windows 每秒进行一次线程切换的频率是多少? [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions Windows 通常 每秒进行一次线
  • IIS / .Net 只允许对给定用户会话进行单个并发响应

    这是我的问题 我们有一个 Net 4 5 Web 表单应用程序 由于服务器端的大量数据访问和操作 应用程序中的某些页面需要很长时间才能加载 如果用户在页面完成加载之前关闭浏览器选项卡 然后打开新选项卡 则新选项卡中对应用程序的任何请求都将挂
  • 将搜索结果更新为 Android 中的 Lazy Adapter

    我有项目列表 想为其实现搜索功能 因此 我有一个带有 addTextChangedListener 的文本框 搜索结果运行良好 但当我尝试将结果设置为 ListView 时 新结果将附加到旧结果中 我正在使用惰性适配器 如何清除适配器中的旧
  • Sub New() 在此上下文中无法访问,因为它是“Friend”

    那么这是什么意思以及如何解决它 如果我将 New 关键字放在下面的行中 则会出现此消息 如果删除它 我会在运行时收到错误消息 提示我需要使用 New 我究竟做错了什么 Dim oPS As AeccPointStyle New AeccPo
  • 如何将 dll 中包含的组件嵌入到 exe 中,以便它可以从内存运行?

    我正在尝试制作一个必须从内存运行的程序 通过Assembly Load bin 如上所述here http www codeproject com Articles 13897 Load an EXE File and Run It fro
  • 对列表中的一系列整数求和

    假设我有一个这样的列表 List
  • 从 SQL 语句中检索元数据(表名)

    我使用的是 Visual Studio 2008 我创建了一个 Winforms 应用程序 并且尝试从 SQL 语句中提取表名 con new SqlConnection connString String queryString Sele
  • 使用属性和性能

    我正在优化我的代码 我注意到使用属性 甚至自动属性 对执行时间有深远的影响 请参阅下面的示例 Test public void GetterVsField PropertyTest propertyTest new PropertyTest

随机推荐

  • Android通过firebase推送Notification(服务器端)

    我正在尝试使用 firebase 云消息传递系统从服务器向我的 Android 设备发送推送通知 我能够成功注册我的设备 并且也为我的设备生成了令牌 我无法使用以下脚本向我的设备发送通知
  • 使用 new 分配内存返回相同的内存地址

    class abc int x int main abc A new abc cout lt lt static cast
  • 当没有剩余内存时,.Net 和 Bitmap 不会被 GC 自动处理

    我想知道 NET 中为位图分配的内存的分配和处置是如何工作的 当我在函数中的循环中创建大量位图并连续调用它时 它将一直工作 直到某个时候位图无法分配内存 给出指定大小的 无效参数 异常 如果我在垃圾收集器工作时调用垃圾收集器 使用以下代码
  • 如何解码 BLE 广告数据

    扫描 BLE 设备后 我调用以下方法 void centralManager CBCentralManager central didDiscoverPeripheral CBPeripheral peripheral advertisem
  • 将两个日期之间的所有日期作为颤振日期范围选择器中的列表返回

    我只从 flutter date range picker 中得到两个日期 但我想要两个选定日期之间的日期列表 感谢您的回答 尝试以下操作 List
  • 如何使用同一应用程序查找附近的 iOS 设备(GPS 位置)

    我想创建一个应用程序 允许用户使用登录到同一应用程序的 GPS 坐标查找附近其他用户的位置 它还可以跟踪正在移动的设备 登录到同一应用程序 的位置在车里 有人能给我概述一下如何实现这一目标吗 有没有免费的 API 可以用来完成这个任务 Da
  • 如何将 png 与 alpha/透明度实时加入帧中

    我正在 OpenCV android 2 4 11 的示例下工作 它使用相机检测面部 我没有在找到的脸上画一个矩形 而是尝试在脸上放置一个遮罩 png 图像 但为了在脸上显示图像 png 图像带有黑色背景 其中有透明度 FdActivity
  • “CL.exe”退出,代码为-1073741515

    我使用的是 Windows 7 64 位机器 我下载了 VC 的 Express 版本和 Windows SDK 我需要在 64 位编译器中编译我的代码 编译时 我收到以下错误 CL exe 退出 代码为 1073741515 这个错误是什
  • 键盘覆盖了我视图底部的文本字段

    我已经搜索过 here 仅当键盘覆盖输入字段时向上移动视图 here 当键盘快速出现时移动文本字段 here 当键盘存在时如何使 UITextField 向上移动 和这里 https developer apple com library
  • Zend_Auth 最佳实践

    我的目标是要求某些页面登录 我正在使用 Zend Framework MVC 并且我正在尝试查找有关最佳实践的示例 关于我正在寻找的内容的一些注释 我希望未登录的用户获得登录框 然后在经过身份验证后返回到页面的登录版本 我想使用依赖注入 并
  • 如何将 LPCSTR 字符串转换为 LPCTSTR 字符串?

    我正在尝试转换LPCSTR串入LPCTSTR细绳 我想连接两个字符串 当我尝试这样时 LPCTSTR str1 L Raja LPCSTR str2 Kumar wcscat s str1 LPCTSTR str2 我发现像 Raja 这样
  • Matlab imshow 无法正确绘图,但 imshowpair 可以正确绘图

    我已经导入了图像 我已将其解析为双精度并对其进行了一些过滤 当我绘制结果时imshow 双像太暗 但是当我使用imshowpair绘制原始图像和最终图像 两个图像都正确显示 我尝试过使用uint8 im2uint8 乘以 255 然后使用这
  • 按位置从 data.table 中提取列作为向量

    如何按位置从 data table 中提取列作为向量 以下是我尝试过的一些代码片段 DT lt data table x c 1 2 y c 3 4 z c 5 6 DT x y z 1 1 3 5 2 2 4 6 我想使用列位置获得此输出
  • JAVA EE CDI 范围、EJB 和托管 Bean 序列化

    对作用域 ejb 和托管 bean 有一些疑问 范围 javax enterprise context ApplicationScope javax enterprise context SessionScope 是否仅适用于 EJB 或者
  • 如何在Python中输入矩阵(二维列表)?

    我尝试创建此代码来输入 m n 矩阵 我本来想输入 1 2 3 4 5 6 但代码产生 4 5 6 4 5 6 当我输入其他 m n 矩阵时 也会发生同样的情况 代码会生成一个行相同的 m n 矩阵 也许你可以帮助我找出我的代码有什么问题
  • 不使用 Oracle 客户端的 Python Oracle DB Connect

    我正在尝试用 python 构建一个应用程序 它将使用安装在企业服务器中的 Oracle 数据库 并且我正在开发的应用程序可以在任何本地计算机中使用 是否可以在Python中连接到oracle DB 而无需在存储和执行python应用程序的
  • 访问共享日历(例如通过 Office 365 REST API 访问会议室)

    我正在使用 Office 365 REST api 访问我帐户的日历 我想要访问我的帐户有权访问的所有日历 特别是 Office 365 界面的 其他日历 部分中显示的会议室日历 现在 如果我查询 https outlook office3
  • 如何使用模糊查找来查找SQL中的句子?

    搜索项 网站上的 ISBN 号 变量 列 MySQL表中的句子 它由许多不同的句子组成 我想找的句子是 自动链接功能随 Google 最新的工具栏一起提供 如果在 Amazon com 网站上找到一本书的 ISBN 编号 它会在网页中提供指
  • 使用 Twilio 留下无环语音邮件消息 [关闭]

    Closed 这个问题需要多问focused 目前不接受答案 我一直在寻找并询问有关此主题的信息 但一无所获 我怀疑这只是数据包数组中的一个命令 任何线索都会有帮助 可以修改调用 REQUEST 数组以注入所需的代码吗 使用 Twilio
  • 实现添加/删除 ListView 项目的撤消/重做操作

    我在尝试在 ListView 控件中实现撤消 重做操作时遇到太多问题 只是为了添加 删除项目 我不久前意识到这里有一个相关问题扩展此类以在列表视图中撤消 重做我开始获得 50 100 200 和 300 点的多重赏金 总共 650 点 但没