实现添加/删除 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 项目的撤消/重做操作 的相关文章

  • 使用 AesManaged“填充无效且无法删除”

    我正在尝试使用 AesManaged 进行简单的加密 解密 但在尝试关闭解密流时不断出现异常 这里的字符串被正确加密和解 密 然后在 Console WriteLine 打印正确的字符串后 我收到 CryptographicExceptio
  • 特殊名称属性还允许哪些其他巧妙的技巧?

    研究中一个问题 https stackoverflow com questions 13259162 vb net power operator overloading from c sharp关于实现 Visual Basic Power
  • 如何隐藏 Windows 窗体中控件的大小调整手柄?

    我有一个 UserControl 想在设计时隐藏调整大小手柄 就像 TextBoxControl 一样 它只有两个手柄 左手柄和右手柄 文本框的高度是固定的 除非你说它是多行的 在这种情况下 文本框会显示所有九个大小调整手柄 您需要实现一个
  • 实体框架 - 循环更新属性

    我正在尝试找到一种方法来循环 EF 对象的属性并更新这些属性的值 更具体地说 我有 50 个字段 其中最多填充 50 个下拉列表 所有 50 个可能都需要填充 也可能不需要填充 为了解决这个问题 我有一个中继器 最多可以创建 50 个 DD
  • 调用退出后应用程序未退出

    我有一个小问题 我似乎无法弄清楚 我正在将 DataGridView 它的内容 保存到 xls 文件中 我这样做没有任何问题 除了在我的任务管理器中它仍然显示它正在运行 我已致电 xlApp Application Quit 这被声明为 D
  • 无法更新 .mdf 数据库,因为该数据库是只读的(Windows 应用程序)

    我使用 C 创建了一个数据库 Windows 应用程序 我的应用程序在 Windows XP 上成功运行 但在 Vista 或 Windows 7 系统上无法正确执行 我的应用程序显示类似以下内容的消息 无法更新 mdf 数据库 因为该数据
  • 无论表单上的焦点控件如何,如何捕获 Keys.F1?

    我使用了 KeyDown 事件和一些简单的代码 例如if e KeyCode Keys F1 捕获在表单上按下 F1 但如果表单上有一些文本框 或者表单上有一些带有 Dock Fill 的电子表格 则上面的代码将毫无用处并且不执行任何操作
  • 编辑 InitializeComponent() 方法 C#

    我已经浏览了多个资源 试图找到何时手动向 InitializeComponent 添加代码的用例 但没有找到任何具体的内容 这表明我们不应该这样做 InitializeComponent 方法中的代码由设计者生成 不应手动修改 https
  • 如何暂时暂停实时数据图表的绘制更新

    我想要 暂停 图表的系列更新来完成一些工作 就像我有一个按钮 当我单击它时 它将暂停图表更新 然后当我单击恢复按钮时 它将更新系列中的所有暂停点 我知道关于 chart1 Series SuspendUpdates 但它似乎不适合我 我使用
  • .NET 组件和 COM 组件有什么区别

    NET 组件和 COM 组件之间有什么区别 有时我们使用 NET 组件包含在我们的项目中 有时我们包含 COM 引用 背后的想法是什么 NET 组件是托管代码 内存处理已为您完成 COM http en wikipedia org wiki
  • 使用对话框周围的语句来确保垃圾收集

    我们有一个包含数千个表单的 Windows 窗体应用程序 其中许多通过 ShowDialog 方法临时显示为对话框 该应用程序已经存在多年 我们发现由于表单或其使用的控件中的各种资源泄漏 许多表单没有及时进行垃圾收集 具体来说 我们发现了未
  • 查询 dns 别名

    我找到了一些code http msdn microsoft com en us library system net dns gethostbyaddress VS 71 aspx来自 msdn 站点 下面包含代码 看起来它将返回给定服务
  • JavaScript:根据文化格式化数字/货币,例如 .NET String.Format()?

    这似乎是一个有人在 2009 年就已经解决的问题 但我找不到一个像样的 JavaScript 库 它需要这样的数字 12345 58 并根据特定区域性 即 nl nl 或 ISO 货币代码正确设置其格式 dojo 表现出了希望 但它默认不包
  • If 语句中 Bool 计算错误

    只是为了好奇 我的代码有这个问题 e被评估为false 我知道通过查看数据库中的数据会得到错误 但 if 语句并不关心这一点 并假设这是真的 并试图抛出异常 有什么想法吗 edit 没有 在第 16 行末尾 价值false是正确的 我已经检
  • .NET 迭代器包装抛出 API

    我有一个带有 API 的类 它允许我请求对象 直到它抛出一个IndexOutOfBoundsException 我想将它包装到一个迭代器中 以便能够编写更清晰的代码 但是 我需要捕获异常以停止迭代 static IEnumerable It
  • 如何将字符串解析为 UNIQUEIDENTIFIER?

    我正在编写一个实体框架 LINQ 查询 其中我想将字符串解析为 UNIQUEIDENTIFIER 又名 GUID 作为WHERE clause public IEnumerable
  • 在服务器桌面会话上捕获屏幕

    我开发了一个 GUI 测试框架 可以按计划对我们公司网站进行集成测试 当出现问题时 它会截取桌面等内容 它在专用 Windows Server 2008 上的登录用户上运行 无人值守 问题是在我已断开远程桌面会话连接的桌面上截取屏幕截图 我
  • ListView 和快照 - 错误 - 错误状态:DocumentSnapshotPlatform 中不存在字段[重复]

    这个问题在这里已经有答案了 我对快照和 ListView 有一个小问题 到目前为止 它运行得很好 但自从我更新了 flutter 和 Dart 后 我 收到了一个错误 构建 StreamBuilder gt 时抛出以下 StateError
  • 如何防止弹出表单夺走父级的焦点

    我有一个小的 windows form 当鼠标悬停在 windows Form 上的某个区域上时 我用它来显示信息 但是当它设置为可见时 它会从父窗口获取焦点 有没有办法防止这种情况 它会导致主窗体在焦点和焦点之间切换时闪烁 时间 2019
  • 如何打开实际上已关闭的 Wifi 适配器的无线电?

    我在用着托管无线网络 http managedwifi codeplex com获取我的 Wifi 适配器的无线电状态 如果收音机实际上已关闭 如何将其打开 像这样的东西 WlanClient wlanClient new WlanClie

随机推荐

  • 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 点 但没