Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time

Code Shelter


Memento is a lightweight and extensible undo framework for .NET applications. It provide undo and redo support for the following events(*) out of the box:

  • Property change
  • Collection element addition
  • Collection element removal
  • Collection element's index change

While these basic events have proved to be sufficient for most applications I've worked with, Memento allows you to build custom events and plug into the framework.

Note: events here mean those actions that cause changes to the system state, e.g. change value of a property etc. They are not .NET events.

Getting Started

Install from NuGet

Install-Package Memento

Create an instance of a Mementor.

var mementor = Mementor.Create();

Note: it's typically sufficient to use one single instance for an entire application. But you can create multiple instances as needed and each of them has a different undo/redo stack. Regardless, make sure you store this instance somewhere easily accessible to other parts of code.

Mark property changes

// Mark change via expression syntax
mementor.PropertyChange(shape, () => shape.Radius);

// Mark change via string name
mementor.PropertyChange(shape, "Radius");

// Mark change with explicit property value (which will be restored to when undo)
mementor.PropertyChange(shape, "Radius", 10);

Mark collection changes

// Addition
mementor.ElementAdd(screen, shape);

// Removal
mementor.ElementRemove(screen, shape);

// Removal with explicit index (to be restored to when undo)
mementor.ElementRemove(screen, shape, index);

// Index change
mementor.ElementIndexChange(screen, shape);

// Index change with explicit index (to be restored to when undo)
mementor.ElementIndexChange(screen, shape, index);

Perform undo and redo

// Undo the last event
if (mementor.CanUndo) mementor.Undo();

// Redo a previous undo
if (mementor.CanRedo) mementor.Redo();


At any point of time, you can reset a Mementor to its original state.


Batch multiple changes

If you want to undo multiple events at once, batch them together.

// Batch via block
mementor.Batch(() => {
	// change events happen here

// Undo all events in the previous batch

// Batch explicitly
// ... sometime later

Disable change marking

If you want to temporarily disable marking (effectively making Mementor ignores all calls to change marking methods like PropertyChange), do one of the followings.

mementor.ExecuteNoTrack(() => { 
	// changes happened in this block are ignored

mementor.IsTrackingEnabled = false;

Event handling

You can be notified when there is change to the undo/redo stack of a Mementor by handling its Changed event. For example if you call Undo(), this event will be fired with the associated undone event.

mementor.Changed += (_, args) => {
	// args allow you to access to the event associated with this notification

Custom events

You can write your own custom event by extending Memento.BaseEvent class. Then you can use it with a Mementor as follows.


Want to learn more?

The comprehensive test suite for Memento should be a good source of reference.



Lightweight and extensible undo framework for .NET ⛺






No releases published

Sponsor this project


No packages published