gpt4 book ai didi

C# CommandManager 结合撤消/重做模式

转载 作者:太空宇宙 更新时间:2023-11-03 13:44:39 24 4
gpt4 key购买 nike

我目前正在寻求将撤消/重做(基于 this 文章)与使用 ICommand 的命令模式相结合。阅读有关 CanExecute 和 CanExecuteChanged 的​​想法后,我发现了 CommandManager,它将更改后的状态传播到所有已注册的 UIElement。但是,如果命令本身存储更改的数据,则似乎很难将这两者结合起来。这是当前情况的示例:

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 会跟踪状态并通知 UIElement。如果我在那里注册命令的每个实例,一个 UIElement 有几个相同的命令竞争 CanExecute 状态。这似乎打破了思路,那么它是如何工作的呢?

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

如果我省略 ICommand 用法,则 wpftutorial.net 的示例会起作用 - 虽然我还没有完全理解那里的操作/撤消操作。

问题

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

编辑:

是否可以在仍然使用 CommandManager 的命令中保存状态?ICommand-Interface 提供了跟踪 CanExecute-State 的功能,这是一个不错的主意。但是,我看不到在命令中保存状态的同时保留这个想法的可能性(因此需要几个不同的实例)。

最佳答案

对于其他遇到这个问题的人:

我现在使用分层 ViewModel 解决了这个问题。每个命令现在都有自己的 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()
{

}

}

关于C# CommandManager 结合撤消/重做模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15784814/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com