假设一个 win 表单具有某些输入字段并且用户输入/重新输入一些数据。
如何保留以前通过“撤消”操作输入的数据?
只是我想知道实现它的最佳方法。
有几个选项。重要的是你在项目的早期就开始设计它。如果在设计时没有考虑到这种功能,那么尝试将其添加到现有项目中可能会非常昂贵。
您需要利用一些基本模式:
MVC或观察者模式。第一个关键不是你的高级架构的宗教或模式狂热者实现。重要的是您的软件能够识别其当前状态和显示状态之间的差异,并适当地解耦。您的视觉状态和应用程序状态之间需要有一个共同的、明确定义的耦合。这为您提供了创建命令所需的通用架构(请参阅#2)。
命令模式。您可以通过命令模式获得很多质量(尽管它可能会以一些看起来应该由向导生成的代码为代价)。您对命令模式采取的具体方法可能会有所不同(每个命令一个类,通过覆盖实现,而每个命令一个类,通过事件处理程序实现,例如),但命令是@Ralph 建议构建堆栈的“动作”类大约。
这可能有点棘手,但一般方法是侦听将数据从视觉状态“提交”到应用程序状态的事件。该Validated
事件可能是一个很好的钩子Textbox
。该Click
事件对于Button
. 当该提交发生时,您创建与该控件关联的命令,尝试执行该命令,如果该命令成功完成,则将该命令添加到您的撤消堆栈。现在,您正在准确跟踪正在发生的事情以及正在发生的数据。
备忘录模式。@JP 解开了最后一块拼图。您可以在保存的命令上使用备忘录来存储受影响控件在执行命令之前的状态。这与UnExecute()
命令界面上的成员相结合,应该是执行任务所需的最后一个核心设计。
像这样的结构化方法的好处是,您现在有了一个自然扩展点,用于需要在命令基础上发生的其他行为。例如,交易是自然而然的选择。在我当前的项目中,我正在使用 WPFICommand
接口(在我的 winforms 项目中)来提供有关是否CanExecute()
在任何给定时间给定命令的反馈。这让我能够以纯命令驱动的方式适当地启用和禁用 UI 小部件。:)
不幸的是,Winforms 内置的这种结构并没有很多支持(据我所知),所以你需要从头开始构建它的大部分。没有一个部分是特别复杂的,但是您会发现自己为每个命令生成了大量的大部分样板代码。这也是一种普遍的设计技术。为了使其有效,它必须在应用程序的适当部分中始终如一地使用。这使得改造功能变得相当昂贵,尤其是在原始代码紧密耦合且没有内聚的情况下。
我不确定 WinForms/.Net 是否具有某种类型的内置撤消功能,您可以利用这些功能。但是您真正需要的是一个 Stack 数据结构来帮助您管理操作列表。您需要创建某种类型的“操作”对象来表示用户可以执行的操作,并且随着他们在应用程序中的进展,您需要将这些操作推送到堆栈上。当他们点击撤消按钮,或 Ctrl-Z 或任何启动撤消操作的方法时,您将弹出当前操作并将应用程序状态恢复到前一个操作。
这是对其工作原理的非常基本和高级别的概述,但我想实现这样的功能可能会变得相当复杂。想象一下它需要如何为像 Adobe Photoshop 这样的程序工作。:O
这可能不是最好的方法,具体取决于您要完成的工作,但您可以使用富文本框并调用该控件中内置的撤消方法。
例如:
richTextBox1.Undo();
CTRL + Z 适用于单个控件。
如果您使用数据和 BindingSource,您可以通过调用CancelEdit函数“撤消”对记录的未持久更改,或者您可以重新加载数据库的数据。
我的建议是在开始设计和实施之前确定具体的撤消要求及其实际好处。我继承了一个 WinForms 应用程序,该应用程序通过内部的一组通用“动作”对象使用了多个操作顺序撤消。然而,事实证明,我与之交谈的应用程序的用户都没有使用或请求该功能!这个特定应用程序的工作方式,如果我是该应用程序的用户,我也不会看到自己使用该功能。
如果是“选择性”撤消,则撤消功能在这种情况下可能会更有用;用户可以在数据提交之前选择之前所做的几个编辑的任何单个操作/编辑,并将该单个编辑恢复到其原始状态,而不是只能先撤消最后一个操作,然后是倒数第二个操作等,这就是它的实现方式。
在任何情况下,该应用程序因此包含不必要的复杂性和间接性,这使得“深入了解”并对现有功能进行更改和增强变得更加困难和缓慢,在这种情况下,对现实世界的好处很少或没有。自从我继承了这个项目,我已经实现了没有撤消的新功能,没有人有任何抱怨。
您可能还发现 Reversi 库很有用,就像其他几个似乎一样。请参阅 [ http://www.codeproject.com/KB/dotnet/reversibleundoredo.aspx][1]或 [this][2]
[1]: http: //www.codeproject.com/KB/dotnet/reversibleundoredo.aspx使您的应用程序可逆以支持撤消和重做
[2]:http ://www.codeproject.com/script/Articles/Article.aspx?aid= 22502 撤消重做
取决于您希望有多少级别的撤消。
您可以在某种意义上将值“提交”到每个控件的表单级别集合中,您可以在单击按钮时“恢复”以供用户返回。