c#命令管理器结合了撤销/重做模式

本文关键字:重做 模式 命令 管理器 结合了 | 更新日期: 2023-09-27 18:07:08

我目前正在使用iccommand将撤消/重做(基于本文)与命令模式结合起来。阅读关于CanExecute和canexecutechange的想法,我发现CommandManager将改变的状态传播到所有注册的ui元素。但是,如果命令本身存储更改的数据,则很难将这两者结合起来。下面是当前情况的一个例子:

interface IUndoCommand : ICommand
{
    void Undo();
}

和实现:

public class SampleCommand : IUndoCommand
{
    private Point oldPosition;
    private Shape shape;
    // Gets the currently moved shape object
    public MoveCommand(Shape shape, Point oldPosition)
    {
        this.oldPosition = oldPosition;
        this.newPosition = new Point(Cavas.GetLeft(shape),Canvas.GetTop(shape));
        this.shape = shape;
    }
    public void Execute(object parameter)
    {
        Model.PersistChanges(shape, newPosition);
    }
    public void Undo()
    {
        Model.PersistChanges(shape, oldPosition);
    }
    public bool CanExecute(object parameter)
    {
    }
    public event EventHandler CanExecuteChanged;
}

在这个实现中,命令存储更改,因此每次执行时都需要创建一个新实例。然而,CommandManager会跟踪状态并通知ui元素。如果我在那里注册命令的每个实例,一个ui元素就会有几个相等的命令竞争CanExecute-state。这似乎打破了这个想法,那么它是如何工作的呢?

当然,我可以移动状态,需要重做/撤消,从命令到模型,并注册一个(静态)命令的实例,将被使用。但实际上我喜欢在命令中存储状态的想法。

如果我省略了ICommand用法的例子wpftutorial.net将工作-虽然我还没有完全得到的想法与行动/撤消行动那里。

你如何结合这些方法,undo/redo + CommandManager?实现在模型中保存状态的唯一解决方案(考虑MVVM为基础)还是有其他机会?

编辑:

是否可以在命令中保存状态,仍然使用CommandManager?iccommand - interface提供了跟踪CanExecute-State的功能,这是一个很好的想法。但是,在命令中保存状态(因此需要几个不同的实例)时,我不认为有可能保留这个想法。

c#命令管理器结合了撤销/重做模式

对于每一个遇到这个问题的人:

我现在解决了这个问题,使用分层视图模型。现在每个命令都有自己的ViewModel了。

public class ViewModel 
{
    public ViewModel()
    {
        MoveCommand = new MoveCommand(this);
    }
    public Shape Shape {get;set;}
    public Point CurrentPosition {get;set;}
    public ICommand MoveCommand {get; private set;}
}

public class MoveCommand
{
    ViewModel viewModel;
    Point shiftVector;
    public MoveCommand(ViewModel viewModel, Point shiftVector)
    {
        this.viewModel = viewModel;
        this.shiftVector = shiftVector;
    }
    public void Execute(object parameter)
    {
        shapeVM.CurrentPosition.X += shiftVector.X;
        shapeVM.CurrentPosition.Y += shiftVector.Y;
    }
    public void Undo()
    {
        shapeVM.CurrentPosition.X -= shiftVector.X;
        shapeVM.CurrentPosition.Y -= shiftVector.Y;
    }
    public bool CanExecute(object parameter)
    {
    }
    // Notice here: the events should be passed to the command manager to take care about it
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove {CommandManager.RequerySuggested -= value;}
    }

分层部分的作用如下:

public class BaseViewModel
{
    ObservableCollection<ViewModels> ViewModels;
    // pass the command from the child's viewModel.
    public ICommand MoveCommand
    {
        get
        {
            return SelectedItem.MoveCommand;
        }
    }
    public SelectedItem ViewModel {get;set;}
    public BaseViewModel()
    {
    }
}