2010-08-25 76 views
5

我正在开发一个Silverlight LoB应用程序,设计人员希望有一个标签界面,类似于Visual Studio的界面(我们可能会使用Telerik Rad控件作为对接标签)。完成原型之后,界面运行良好,但我在考虑如何在MVVM项目中实现撤销/重做功能时遇到问题。如何在MVVM应用程序中实现撤销/重做?

撤消/恢复功能有:

  1. 上的撤消/重做,UI状态,即 返回焦点,选择等恢复到 控制(一个或多个)(例如一个文本框) 这个变化源于。
  2. 拥有按次撤销/重做堆栈

通常情况下,我会用命令的模式,但我不知道如何应用与MVVM。

我已经使用了命令&绑定来获得理想化的视图模型的松散耦合,但它使撤销/重做变得更加棘手,因为视图模型没有任何视图的概念以及接收到命令或绑定属性发生变化时的视图状态。似乎我需要某种服务跟踪,无论何时用户执行一些可撤销操作并获取状态以供以后恢复时,该视图都处于活动状态。

对于在MVVM中实现撤消/重做的最佳实践有什么共识吗?我非常关心丹尼尔沃恩如何在他的钙项目中做到这一点; Blend显然是使用MVVM模式编写的,它的行为与我想要的应用程序一样,如果MS解释他们是如何做到的,那就太棒了!

回答

2

您需要做的第一件事是确保您完全将操作与界面分开。这意味着将影响数据的所有操作转换为离散操作。这也意味着无论是什么原因导致观点转变,也应该记录为一个独立的行动。基本上,界面的状态应该只反映数据更改和基于命令的视图更改(请参阅下面有关视图更改的最后一个注释)。

我们以前使用过的最成功的撤消系统允许嵌套IUndoableCommand对象。这些复合命令汇总为单个用户操作(您希望在“撤消”菜单中显示的那种操作)。

我注意到你提及在视图中使用撤消...这似乎是一个多种应用程序的不寻常的行为。通常,撤消操作仅在单个控件和任何拖放操作中进行。例外通常是基于图形的接口(不是基于表单的)。在撤消过程中更改表单将等同于MS Word切换到另一个文档并继续撤销...对最终用户非常不利。可能想让用户体验人员重新考虑设计的这一方面。只是我的2美分价值。

希望这会有所帮助。

+0

我现在也将根据你提到的调查钙项目。感谢那。 – 2010-08-25 18:02:44

+0

感谢您的回答,HiTech。当你说“撤销仅在单个控件中”时,你的意思是,例如,在一个带有几个文本框的窗体(视图)上,用户必须关注一个文本框,在该文本框中为他进行更改以撤销/重做他通过TextBox所做的任何更改?将操作与接口完全分开 - 是否意味着禁止视图中的控件与视图模型中的属性之间的双向绑定?不幸的是,我们的应用程序具有交互式绘图表面(画布)和Blend/VS等形式;这很复杂。 绝对感谢您的想法! – JamesCo 2010-08-26 13:26:56

1

@JamesCo,

我实现了撤销/重做一个WPF应用程序,并最终发布我的撤销/重做代码http://muf.codeplex.com/。你也可以通过NuGet获取它。只需查找“MUF”或“受监视的撤消框架”即可。它包括对Silverlight 4.0以及.NET 3.5,4.0和WP7的支持。

我的WPF应用程序也使用MVVM,在某些情况下,确实允许撤消选择更改等操作。我还跟踪了WPF框架中显示的活动“页面”,以便用户移回到撤消操作应该应用的页面。

该库采用灵活的方法来编写撤消/重做每个步骤的操作。最终,它只需要一个代表撤消和一个代表重做。你可以让这些代表做你喜欢的任何事情。库中包含一个默认的实现,它只是简单地使用对象,属性名称,旧值和新值。它构建基于反射的代表,根据需要应用旧值或新值。

就隔离每个视图的更改而言,该库允许为每个“文档”或“容器”保留单独的撤消/重做操作堆栈。您只需传递对容器的引用即可获得关联的撤销/重做堆栈。

最后,该库包含对批处理更改的支持。在多个行动应该作为一个整体撤回的时候,这很有用。

欢迎对codeplex网站(http://muf.codeplex.com/)提出意见和问题。您还会在那里找到完整的文档和示例应用程序。