我有一个带有DataGrid
的简单WPF屏幕和一些用于剪切,复制,粘贴和删除行的按钮:
我想为所有操作实现Undo/Redo
功能,例如剪切/复制/粘贴/添加/删除等。如果它们提供了一些好处,我可以使用其他集合控件而不是DataGrid
其他。我已经在stackoverflow.com上讨论了关于同一主题的一些其他问题,但是没有发现它们有用。
答案 0 :(得分:2)
我认为这个功能最容易使用特殊框架实现,它们通常不大且免费。有许多框架允许您实现Undo/Redo
功能。我个人喜欢GuiLabs.Undo
,他是我用过的最简单,最舒服的人之一。工作的重点在action
:
每个操作都会对您的域模型进行更改。准备Action的过程明确地与执行它分开。行动的执行可能在准备和安排后的更晚阶段进行。任何Action实现
IAction
并且基本上提供了两种方法:一种用于实际执行这些操作,另一种用于撤消它。
最重要的是创建一个 AbstractAction 接口类并将其保存在正确的位置。您必须使用ActionManager
来保留将来要撤消的操作:
private void SomeActionLogic()
{
MyAction action = new MyAction(parameter);
actionManager.RecordAction(action);
}
然后在某个地方使用Undo/Redo
:
actionManager.Undo();
...
actionManager.Redo();
那么您是否需要考虑如何使用AbstractAction
类中的集合?也许这对资源来说是劳动密集型的,因为每次触发Undo/Redo
时都需要处理集合。
使用的简单示例,取自here
:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Original color");
SetConsoleColor(ConsoleColor.Green);
Console.WriteLine("New color");
actionManager.Undo();
Console.WriteLine("Old color again");
using (Transaction.Create(actionManager))
{
SetConsoleColor(ConsoleColor.Red); // you never see Red
Console.WriteLine("Still didn't change to Red because of lazy evaluation");
SetConsoleColor(ConsoleColor.Blue);
}
Console.WriteLine("Changed two colors at once");
actionManager.Undo();
Console.WriteLine("Back to original");
actionManager.Redo();
Console.WriteLine("Blue again");
Console.ReadKey();
}
static void SetConsoleColor(ConsoleColor color)
{
SetConsoleColorAction action = new SetConsoleColorAction(color);
actionManager.RecordAction(action);
}
static ActionManager actionManager = new ActionManager();
}
class SetConsoleColorAction : AbstractAction
{
public SetConsoleColorAction(ConsoleColor newColor)
{
color = newColor;
}
ConsoleColor color;
ConsoleColor oldColor;
protected override void ExecuteCore()
{
oldColor = Console.ForegroundColor;
Console.ForegroundColor = color;
}
protected override void UnExecuteCore()
{
Console.ForegroundColor = oldColor;
}
}
答案 1 :(得分:1)
您应该实施Command Pattern
使用此模式,每个操作都有一个反作用(重做/撤消)。您在堆栈中保存已应用和未撤消的命令。这将允许您撤消和重做所有命令。 WPF非常适合这种情况,因为您可以将命令直接绑定到元素,而不是普通事件。