撤消WPF MV-VM内部,它是如何适应的?

dec*_*jau 12 c# wpf undo mvvm

在我之前的项目中,我已经在c ++中实现了undo系统,我知道它是如何工作的.我也知道Command模式.

我将实现一个C#/ WPF桌面应用程序,并希望将我的设计基于MV-VM模式.

该申请将:

  • 是一个相对较小的项目(2-3周估计工作为1开发)
  • 有一个简单的数据模型与持久性(linq到XML)
  • 支持撤消/重做

我想知道是否有人在遵循MV-VM模式时有实施撤销系统的经验.它怎么会适合它?它如何从INotifyPropertyChanged和INotifyCollectionChanged通知中受益,因此在实现模型(业务对象)时需要最少的工作.

我认为撤销系统会某种程度集成到ViewModel层中,因为它是一种UI状态.

任何想法?

dec*_*jau 13

这是我用于项目的解决方案.证明解决方案完美无缺.

系统正在使用撤消事件对象,其中每个撤消事件都知道如何撤消和重做自身.

interface IUndoEvent
{
    void Undo();
    void Redo();
}
Run Code Online (Sandbox Code Playgroud)

我只能通过实现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)
    }
}
Run Code Online (Sandbox Code Playgroud)

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); }
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,还有一个UndoManager(项目单例),用于存储撤消堆栈和重做堆栈.