DefaultUnDo介绍
DefaultUnDo:为 .NET 应用轻松添加撤销/重做功能
在开发桌面应用、编辑器或其他需要用户交互的软件时,撤销(Undo)和重做(Redo) 功能几乎是标配。然而,实现一个健壮、易用的撤销/重做系统并不简单,需要考虑命令模式、历史栈管理、事务合并等诸多细节。
DefaultUnDo 正是为此而生的开源库。它是一个基于命令模式(Command Pattern) 的轻量级 .NET 库,旨在以最简单的方式为应用程序集成撤销/重做功能。
一、核心概念:一切从 UnDoManager 开始
DefaultUnDo 的使用极其直观。你只需要创建一个 UnDoManager 实例,它便是整个撤销/重做系统的核心,负责记录操作历史和管理撤销/重做的状态。
IUnDoManager manager = new UnDoManager();
随后,你可以通过 manager.Do() 方法执行一个操作,并同时提供执行(do)和撤销(undo)两个对应的委托。
int number = 42;
// 执行操作:将 number 改为 100;撤销操作:将 number 改回 42
manager.Do(
() => number = 100, // doAction
() => number = 42 // undoAction
);
当需要撤销时,只需调用 manager.Undo();需要重做时,调用 manager.Redo()。CanUndo 和 CanRedo 属性则用于判断当前是否有操作可以撤销或重做。
if (manager.CanUndo)
{
manager.Undo(); // number 回到 42
}
if (manager.CanRedo)
{
manager.Redo(); // number 回到 100
}
二、便捷用法:让常见操作更简单
对于修改字段或属性值这类高频场景,DefaultUnDo 提供了便捷的重载方法,无需手动编写 do/undo 委托。
int score = 10;
// 直接将 score 从 10 改为 99,库会自动记录旧值用于撤销
manager.Do(v => score = v, 99, score);
三、高级特性:事务与嵌套
在实际业务中,我们常常需要将多个操作合并为一个原子操作,即要么全部执行成功,要么全部撤销。DefaultUnDo 通过事务(Transaction) 完美支持这一需求。
using (IUnDoTransaction transaction = manager.BeginTransaction())
{
manager.Do(() => value = 10, () => value = 0);
manager.Do(() => value = 20, () => value = 10);
transaction.Commit(); // 提交事务,两个操作合并为一个撤销单元
}
// 一次 Undo() 会同时撤销两个操作
manager.Undo(); // value 回到 0
此外,Do 方法本身也支持嵌套操作,嵌套内部的操作会被自动合并到外层操作中,一次 Undo 即可回退全部。
四、与 MVVM 模式的无缝集成
DefaultUnDo 对 MVVM(Model-View-ViewModel)模式提供了良好的支持。库中内置了 UnDoField<T> 类型,可以方便地创建支持撤销/重做的可绑定属性。
public class MyViewModel : ANotifyPropertyChanged
{
private UnDoField<string> _name;
public string Name
{
get => _name;
set => SetProperty(manager, ref _name, value);
}
}
通过这种方式,ViewModel 中的属性变更会自动记录到撤销历史中,极大简化了 MVVM 应用中撤销功能的实现。
五、要求与安装
-
兼容性:支持 .NET Standard 2.0,因此可广泛应用于 .NET Framework 4.8、.NET Core 以及 .NET 5/6/8 等各类项目。
-
安装:通过 NuGet 包管理器即可轻松安装。
dotnet add package DefaultUnDo
或通过 Visual Studio 的 NuGet 包管理器搜索 DefaultUnDo 进行安装。
六、总结
DefaultUnDo 是一个设计精巧、使用简单的撤销/重做库。它基于经典的命令模式,通过 UnDoManager 统一管理操作历史,并提供了便捷的 API 和与 MVVM 的深度集成。无论你是在开发一个复杂的桌面应用,还是需要一个轻量级的撤销方案,DefaultUnDo 都是一个值得尝试的选择。

浙公网安备 33010602011771号