如何通过“撤销”操作保留先前输入的数据?
我想知道实现这个功能的最佳方法。
有几个选择。重要的是您要在项目早期开始设计它。如果没有考虑到这种功能,试图将其添加到现有项目中可能会非常昂贵。
有几个基本模式可以利用:
MVC或Observer模式。第一个关键点不是你高级架构的宗教或模式狂热实现,而是你的软件识别其当前状态和显示状态之间的差异,并适当地解耦。需要在视觉状态和应用程序状态之间建立通用、清晰定义的耦合。这为你提供了创建命令所需的共同架构(参见#2)。
Command模式。使用命令模式可以获得很多质量(虽然可能会以一些看起来应该由向导生成的代码为代价)。你采取的具体命令模式方法可能会有所不同(每个命令一个类,通过覆盖实现,或每个命令多个类,通过事件处理程序实现,例如),但命令是@Ralph建议围绕堆栈构建的“操作”类。
这可能有点棘手,但一般的方法是监听一个事件,该事件将从视觉状态提交数据到应用程序状态。Validated
事件可能是Textbox
的好钩子。Click
事件对于Button
更有意义。当发生提交时,你创建与该控件相关联的命令,尝试执行命令,并将命令添加到撤消堆栈中,如果命令成功完成。现在你正在跟踪正在发生的事情以及它正在使用的数据。
Memento模式。@JP提出了最后一块拼图。你可以在保存的命令上使用备忘录来存储命令执行前受影响控件的状态。这与你命令接口上的UnExecute()
成员结合使用,应该是你需要执行任务的最后一个核心设计部分。
ICommand
接口(在我的winforms项目中)来提供有关给定命令是否在任何给定时间CanExecute()
的反馈。这让我以纯粹的命令驱动方式适当地启用和禁用UI小部件。 :)根据您想要达到的目标,这可能不是最好的方法,但您可以使用richtextbox并调用该控件内置的撤消方法。
例如:
richTextBox1.Undo();
CTRL + Z 可以在单个控件上使用。
如果您正在使用数据和 BindingSource,您可以通过调用 CancelEdit 函数来“撤消”未持久化的记录更改,或者您可以重新加载数据库中的数据。
你可能会发现Reversi库很有用,因为其他一些人也这样认为。请参见[http://www.codeproject.com/KB/dotnet/reversibleundoredo.aspx][1]或[此][2]
[1]: http://www.codeproject.com/KB/dotnet/reversibleundoredo.aspx 使您的应用程序可逆以支持撤消和重做
[2]: http://www.codeproject.com/script/Articles/Article.aspx?aid=22502 撤消重做
我的建议是在开始设计和实现之前确定具体的撤消需求及其实际效益。我曾经接手过一个WinForms应用程序,它通过内部通用“操作”对象堆栈使用多次操作顺序撤消。然而,事实证明,我与该应用程序的所有用户都没有使用或请求此功能!而且这个特别的应用程序的工作方式,如果我是该应用程序的用户,我也不会看到自己使用此功能。
如果它是一种“选择性”撤消,那么在这种情况下,撤消功能可能会更有用;在数据提交之前,用户可以选择任何单个操作/编辑以还原该单个编辑到其原始状态,而不仅仅能够首先撤消上一个操作,然后是倒数第二个操作等等,这就是它的实现方式。
无论如何,该应用程序因此包含不必要的复杂性和间接性,使得对现有功能进行修改和增强变得更加困难和缓慢,而实际上并没有或几乎没有真正的世界效益。自从我接手这个项目以来,我已经实现了新的功能,没有撤消,也没有人抱怨过。
这取决于您希望拥有多少级撤销。
您可以在提交之前将值存储到某种程度上的表单级集合中,以便为每个控件进行“还原”,用户可以在单击按钮时返回。