在我以前的项目中,我已经在c ++中实现了undo系统,我知道它是如何工作的。我也知道Command模式。
我将实现一个C#/ WPF桌面应用程序,并希望将我的设计基于M-V-VM模式。
申请将:
我想知道是否有人在遵循M-V-VM模式时有实施撤销系统的经验。它怎么会适合它?它如何从INotifyPropertyChanged和INotifyCollectionChanged通知中受益,因此在实现模型(业务对象)时需要最少的工作。
我认为撤销系统会某种程度集成到ViewModel层中,因为它是一种UI状态。
有什么想法吗?
答案 0 :(得分:13)
这是我用于项目的解决方案。证明该解决方案运行良好。
系统正在使用撤消事件对象,其中每个撤消事件都知道如何撤消和重做自己。
interface IUndoEvent
{
void Undo();
void Redo();
}
我能够通过仅实现2个撤消事件来构建系统:一个用于属性更改;一个用于收集更改。
这个想法是这些事件通过直接修改模型来实现撤销/重做。
class PropertyChangeUndoEvent : IUndoEvent
{
private ModelBase _target;
private string _propertyName;
private object _oldValue;
private object _newValue;
public PropertyChangeUndoEvent(ModelBase target, string propertyName, object oldValue, object newValue)
{
_target = target;
_propertyName = propertyName;
_oldValue = oldValue;
_newValue = newValue;
}
public void Undo()
{
SetValue(_oldValue);
}
public void Redo()
{
SetValue(_newValue);
}
private void SetValue(object value)
{
// Set Value on the _target using reflection (_propertyName)
}
}
ViewModel通过调用ViewModelBase函数来处理创建撤消事件:
class MyViewModel : ViewModelBase
{
public string Name
{
get { return _model.Name; }
// The SetValue will create a undo event, and push it to the UndoManager
set { SetValue(_model, "Name", value); }
}
}
最后,还有一个UndoManager(项目单例),用于存储撤消堆栈和重做堆栈。
答案 1 :(得分:4)
您可能会发现Monitored Undo Framework非常有用。 http://muf.codeplex.com/。它不使用“自上而下”命令模式,而是在发生更改时监视更改,并允许您将委托放在撤消堆栈上以反转更改。
我将其创建为使用MVVM构建的WPF应用程序的一部分。大多数撤消操作都源自我们的底层域模型,但我们也迷上了ViewModel的某些区域以允许撤消/重做。
您可以在http://muf.codeplex.com/找到有关codeplex网站的更多信息和文档。
答案 2 :(得分:2)
我想你将Command模式与Memento结合在一起?
我认为撤销系统会某种程度集成到ViewModel层中,因为它是一种UI状态。
?通常,undo / redo作用于业务对象,UI反映业务层。
假设我们有一个带有“描述”字符串的产品类。 ProductVM公开了一个引发PropertyChanged的字符串属性。 在修改时,纪念品保留旧的模型实例。如果撤消,请使用ProductVM.Description =(memento as Product)恢复纪念品。描述:模型将更新,UI也会更新。
注意:避免(memento as Product),仅针对样本;)