如何在.net windows应用程序中实现“撤销”操作?

时间:2009-04-29 05:00:11

标签: .net winforms undo-redo

假设,win表单具有某些输入字段,用户输入/重新输入一些数据。

如何保留“撤消”操作先前输入的数据?

我想知道实现它的最佳方法。

9 个答案:

答案 0 :(得分:14)

有几个选择。重要的是你在项目的早期开始设计它。如果没有考虑到这种能力,尝试将它添加到现有项目中可能非常昂贵。

您可能希望利用以下几种基本模式:

  1. MVCObserver模式。第一个关键不在于您的高级架构的宗教或模式 - 狂热实现。 重要的是,您的软件会识别其当前状态与显示状态之间的差异,并适当地解耦。您的可视状态和应用程序状态之间需要有一个共同的,明确定义的耦合。这为您提供了创建命令所需的通用架构(参见#2)。

  2. Command模式。使用命令模式可以获得很多质量(尽管它可能以某些代码为代价,看起来应该是向导生成的代码)。您对命令模式采取的具体方法可能有所不同(每个命令一个类通过覆盖实现,而每个命令通过事件处理程序实现一个类,例如),但命令是@Ralph建议构建堆栈的“action”类周围。

    这可能有点棘手,但一般的方法是侦听将视觉状态“提交”到应用程序状态的事件。 Validated事件可能是Textbox的一个好钩子。 Click事件对Button更有意义。当提交发生时,您创建与该控件关联的命令,尝试执行该命令,并在命令成功完成时将命令添加到撤消堆栈。现在,您正在准确地跟踪正在发生的事情以及它正在发生的数据。

  3. Memento模式。 @JP拉出最后一块拼图。您可以在保存的命令上使用纪念品来存储执行命令之前受影响控件的状态。这与命令界面上的UnExecute()成员相结合,应该是执行任务所需的最后一个核心设计。

  4. 这样的结构化方法的优点在于,您现在可以在需要基于命令的情况下获得额外行为的自然扩展点。例如,交易是很自然的。在我当前的项目中,我正在使用WPF ICommand接口(在我的winforms项目中)来提供有关给定命令CanExecute()在任何给定时间的反馈。这使我可以以纯粹的命令驱动方式适当地启用和禁用UI小部件。 :)

    不幸的是,Winforms内置的这种结构并不是很多支持(据我所知),所以你需要从头开始构建大部分内容。没有一件事特别复杂,但你可以发现自己为每个命令生成了大量的大部分样板代码。它也是一种普遍的设计技术。为了使其有效,必须在应用程序的适当部分中始终如一地使用它。这使得改进功能非常昂贵,特别是如果原始代码紧密耦合且不连贯。

答案 1 :(得分:3)

我不确定WinForms / .Net是否具有某种类型的内置撤消功能,您可以利用它。但您真正需要的是Stack数据结构,以帮助您管理操作列表。您需要创建某种类型的“操作”对象来表示用户可以执行的操作,并且当他们在应用程序中前进时,您需要将这些操作推送到堆栈上。当他们点击撤消按钮或Ctrl-Z或任何启动撤消操作的方法时,您将弹出当前操作并将应用程序状态恢复为上一个操作。

这是一个非常基本和高级别的概述,它将如何工作,但我想,实现这样的功能可能会变得非常复杂。想象一下它如何适用于像Adobe Photoshop这样的程序。 :o

答案 2 :(得分:2)

根据您要完成的操作,这可能不是最好的方法,但您可以使用richtextbox并调用内置于该控件中的撤消方法。

例如:

richTextBox1.Undo();

答案 3 :(得分:1)

Thisthis可能会有所帮助。

答案 4 :(得分:1)

CTRL + Z适用于各个控件。

如果您使用数据和BindingSource,您可以通过调用CancelEdit函数“撤消”对记录的未持久更改,或者您可以重新加载数据库的数据。

答案 5 :(得分:1)

我的建议是在开始设计和实施之前确定具体的撤销要求及其实际好处。我继承了一个WinForms应用程序,该应用程序在内部通过一堆通用“动作”对象使用多个操作顺序撤消。然而,事实证明我所使用的应用程序的用户都没有使用也没有请求该功能!这个特定的应用程序的工作方式,如果我是该应用程序的用户,我也不会看到自己使用该功能。

如果是“选择性”撤消,撤销功能在这种情况下可能更有用;用户可以选择在数据提交之前进行的多个先前编辑的任何单个操作/编辑,并将该单个编辑恢复到其原始状态,而不是仅能够首先撤消上一个操作,然后是倒数第二个操作等等,它是如何实施的。

在任何情况下,应用程序因此包含不必要的复杂性和间接性,使得“grok”更难和更慢,并且对现有功能进行更改和增强,在这种情况下很少或没有现实世界的好处。自从我继承了这个项目以来,我已经实现了新功能而没有撤消,没有人抱怨过。

答案 6 :(得分:1)

您可能还发现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撤消重做

答案 7 :(得分:1)

答案 8 :(得分:0)

取决于您希望拥有多少级别的撤消。

您可以将值在某种意义上“提交”之前存储到每个控件的表单级别集合中,您可以在单击按钮时“还原”以便用户返回。