在已经正常运行的应用程序中撤消WPF / C#中的重做

我已经就如何实现这个问题的标题做了一些研究。我正在开发的应用程序已经开发了几年左右(虽然进展缓慢,但你们都知道它在现实世界中的表现如何)。现在要求我放入Undo / Redo多级功能。现在说“在开始之前你应该考虑过这个问题”已经有点晚了......好吧,我们确实考虑过这个问题 - 我们对它没有做任何事情,现在它就是这样。从搜索SO(和外部链接)我可以看到两种最常见的方法似乎是...... 命令模式 纪念品模式 命令模式看起来像是一项很多工作,我只能想象它在这个过程中会抛出数千个错误,所以我真的不喜欢那个。 Memento模式实际上与我脑子里的模式很像。我在想是否有某种方法可以快速拍摄当前在内存中的对象模型的快照,然后我就可以将它存储在某个地方(也可能存储在内存中,也可能存储在文件中)。这似乎是一个好主意,我能看到的唯一问题是它如何与我们已经编写的内容集成。您可以看到应用程序,因为它在大面板(可能是数百个)中绘制图像,然后允许用户通过UI或通过自定义构建的属性网格来操作它们。整个应用程序与一个大的观察者模式相关联。第二个任何变化,事件被触发,所有需要更新的事情都会发生。这很好,但我不能帮助以为如果用户在属性网格上的文本域中输入文本,在UI赶上之前会有一些延迟(似乎每次用户按下一个键时,都会添加一个新的快照到撤消列表)。所以我的问题是...... 你知道可能有效的Memento模式的任何好的替代品吗? 你认为Memento模式适合这里还是会减慢应用程序的速度。 如果Memento模式是要走的路,那么制作对象模型快照的最有效方法是什么(我正在考虑序列化它或什么的) 快照应该存储在内存中还是可以将它们放入文件中? 如果你有这么远,那么请你好好阅读。您的任何输入都将非常有价值,非常感谢。     
已邀请:
撤消/重做的关键是 了解您需要保存和恢复的状态 知道什么时候需要保存状态 在事实之后添加撤消/重做总是一件痛苦的事情 - (我知道这个评论对你来说没用,但是在你开始之前总是最好在应用程序框架中设计支持,因为它可以帮助人们使用undo-整个发展中的友好模式)。 可能最简单的方法是基于纪念品的方法: 找到构成“文档”的所有数据。你能以某种方式统一这些数据,以便形成一个连贯的整体吗?通常,如果您可以将文档结构序列化为文件,那么您需要的逻辑就是在序列化系统中,这样就可以为您提供一种方法。直接使用它的缺点通常是您通常必须序列化所有内容以便撤消将是巨大而缓慢的。如果可能的话,重构代码,以便(a)在整个应用程序中使用一个通用的序列化接口(因此可以使用通用调用保存/恢复数据的任何部分),以及(b)每个子系统都被封装因此,对数据的修改必须通过一个公共接口(而不是很多人直接修改成员变量,他们应该调用对象提供的API来请求它对自己进行更改)和(c)每个子 - 部分数据保留“版本号”。每次进行更改(通过(b)中的接口),都应该增加该版本号。这种方法意味着您现在可以扫描整个文档并使用版本号查找自上次查看以来已更改的部分,然后序列化最小量以保存并恢复更改后的状态。 提供一种机制,可以记录单个撤消步骤。这意味着允许多个系统更改数据结构,然后在更新所有内容后触发撤消记录。确定何时执行此操作可能会非常棘手,但通常可以通过在UI完成处理每个输入事件时在消息循环中扫描文档以进行更改(参见上文)来完成。 除此之外,我建议采用基于命令的方法,因为除了撤消/重做之外,还有很多好处。     
好吧,这是我对这个问题的看法。 1-您需要多级撤消/重做功能。所以你需要存储可以存储在堆栈中的用户操作。 2-你的第二个问题是如何通过Memento模式来识别操作所改变的内容,这是一个相当大的挑战。纪念品是关于在你的记忆中扭曲初始对象状态。 或者,您需要存储操作更改的内容,以便您可以使用此信息来撤消操作。 命令模式是为Undo / Redo功能而设计的,我想说它的实施时间已经很晚了,但实际上已经使用了几年并适用于大多数应用程序的设计。     
如果性能允许,您可以在每个操作之前序列化您的域。如果对象本身不大,那么几百个对象就不多了。 由于您的对象图可能非常简单(即使用继承,循环,...),因此集成的XmlSerializer和JsonSerializer是不可能的。 Json.net支持这些,但在某些类型(本地DateTimes,数字......)上做了一些有损转换,所以它也很糟糕。 我认为protobuf序列化程序需要某种形式的DTD(.proto文件)或所有属性的装饰,其属性将其名称映射到数字,因此它可能不是最佳的。 BinaryFormatter可以序列化大多数东西,你只需要使用[Serializable]属性来装饰所有类。但我自己并没有使用它,所以可能会有一些我不知道的陷阱。也许与单身人士或事件有关。     
您可能会发现Monitored Undo Framework非常有用。 http://muf.codeplex.com/ 它使用与memento模式类似的东西,通过监视发生的变化,并允许您将委托放在撤消堆栈上,以反转/重做更改。 我考虑过一种方法,它会对文档进行序列化/反序列化,但却担心会产生开销。相反,我通过属性库监视属性上的模型(或视图模型)中的更改。然后,根据需要,我使用MUF库“批处理”相关更改,以便它们作为更改单位撤消/重做。 您的UI设置可以对底层模型中的更改做出反应这一事实很好。听起来你可以在那里注入撤消/重做逻辑,并且更改会冒泡到UI。 我不认为你会看到很多滞后或性能下降。我有一个类似的应用程序,我们根据模型中的数据呈现图表。到目前为止,我们已经取得了很好的成绩。 您可以在http://muf.codeplex.com/上找到有关codeplex站点的更多信息和文档。该库也可通过NuGet获得,支持.NET 3.5,4.0,SL4和WP7。     

要回复问题请先登录注册