【问题标题】:Undo inside WPF M-V-VM, how does it fit?在 WPF M-V-VM 中撤消,它如何适应?
【发布时间】:2010-10-28 08:06:34
【问题描述】:

在我之前的项目中,我已经用 C++ 实现了撤销系统,我知道它是如何工作的。我也知道命令模式。

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

应用程序将:

  • 是一个相对较小的项目(1 个开发人员预计需要 2-3 周的工作时间)
  • 拥有一个具有持久性的简单数据模型(linq to XML)
  • 支持撤消/重做

我想知道是否有人在遵循 M-V-VM 模式时有实施撤消系统的经验。它如何融入其中?它如何从 INotifyPropertyChanged 和 INotifyCollectionChanged 通知中受益,因此在实现模型(业务对象)时所需的工作最少。

我认为撤消系统会以某种方式集成到 ViewModel 层中,因为它是一种 UI 状态。

有什么想法吗?

【问题讨论】:

    标签: c# wpf mvvm undo


    【解决方案1】:

    这是我用于项目的解决方案。事实证明,该解决方案运行良好。

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

    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(项目单例),用来存放undo stack和redo stack。

    【讨论】:

      【解决方案2】:

      您可能会发现受监控的撤消框架很有用。 http://muf.codeplex.com/。它不使用“自上而下”命令模式,而是在更改发生时监视更改,并允许您在撤消堆栈上放置一个委托来撤消更改。

      我将它创建为使用 MVVM 构建的 WPF 应用程序的一部分。大多数撤消操作源自我们的底层域模型,但我们也连接到 ViewModel 的某些区域以允许在那里撤消/重做。

      您可以在http://muf.codeplex.com/ 的 codeplex 站点上找到更多信息和文档。

      【讨论】:

        【解决方案3】:

        我想你正在将命令模式与备忘录结合起来?

        我认为撤消系统会以某种方式集成到 ViewModel 层中,因为它是一种 UI 状态。

        ?!通常,undo/redo 作用于业务对象,UI 反映业务层。

        假设我们有一个带有“描述”字符串的产品类。 ProductVM 公开了一个引发 PropertyChanged 的​​字符串属性。 在修改时,纪念品会保留旧的模型实例。如果您撤消,请使用 ProductVM.Description = (memento as Product).Description 恢复备忘录:模型将更新,UI 也会更新。

        注意:避免(作为产品的纪念品),仅用于示例;)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-09-25
          • 2010-10-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-02
          • 1970-01-01
          相关资源
          最近更新 更多