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的功能,这是一个很好的想法。但是,在命令中保存状态(因此需要几个不同的实例)时,我不认为有可能保留这个想法。
对于每一个遇到这个问题的人:
我现在解决了这个问题,使用分层视图模型。现在每个命令都有自己的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()
{
}
}