> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/uwp/get-started/samples/undoredotest.md).

# UndoRedoTest

Sample C# code for using Apryse SDK to take snapshots of edits and move between them using the API.

The Apryse SDK has a low-level facility for undo and redo operations. It is a API that applies to any edits made to a particular document (not just annotations). This sample C# code shows how to use Apryse SDK to walk back and forth on a fully general, bit-exact list of document states. Saving changes in a mode that is not 'incremental' will wipe out the undo-redo state list; the API will not be able to access old snapshots anymore. See the [undoing and redoing guide](/core/pdf-editing/undoredo.md) for more information. Learn more about our [UWP SDK](/core/get-started/frameworks/dotnet.md).

{% tabs %}
{% tab title="C#" %}
{% code lineNumbers="true" %}

```csharp
//
// Copyright (c) 2001-2020 by PDFTron Systems Inc. All Rights Reserved.
//

using System;
using System.IO;
using System.Threading.Tasks;
using Windows.Foundation;

using pdftron.PDF;
using pdftron.SDF;

using PDFNetUniversalSamples.ViewModels;
using pdftron.Common;

namespace PDFNetSamples
{
    public sealed class UndoRedoTest : Sample
    {
        public UndoRedoTest() :
            base("UndoRedo", "The following sample illustrates how to use the UndoRedo API.")
        {
        }

        public override IAsyncAction RunAsync()
        {
            return Task.Run(new System.Action(async () => {
                WriteLine("--------------------------------");
                WriteLine("Starting UndoRedo Test...");
                WriteLine("--------------------------------\n");

                bool error = await UndoRedoTestAsync();

                if (error)
                {
                    WriteLine("UndoRedo failed");
                }
                else
                {
                    WriteLine("UndoRedo succeeded");
                }

                WriteLine("\n--------------------------------");
                WriteLine("Done UndoRedo Test.");
                WriteLine("--------------------------------\n");
            })).AsAsyncAction();
        }

        private async Task<bool> UndoRedoTestAsync()
        {
            bool error = false;

            // Relative path to the folder containing test files.
            string inputPath = Path.Combine(InputPath, "newsletter.pdf");
            string inputImagePath = Path.Combine(InputPath, "peppers.jpg");
            string outputPath = Path.Combine(OutputPath, "addimage.pdf");
            string outputUndoPath = Path.Combine(OutputPath, "addimage_undone.pdf");
            string outputRedoPath = Path.Combine(OutputPath, "addimage_redone.pdf");

            try
            {
                // Open the PDF document.
                PDFDoc document = new PDFDoc(inputPath);
                ElementBuilder elementBuilder = new ElementBuilder(); // Used to build new Element objects	
                ElementWriter elementWriter = new ElementWriter();	// Used to write Elements to the page                	

                UndoManager undoManager = document.GetUndoManager();

                // Take a snapshot to which we can undo after making changes.
                ResultSnapshot snapshot0 = undoManager.TakeSnapshot();
                DocSnapshot snapshot0State = snapshot0.CurrentState();

                Page page = document.PageCreate();   // Start a new page

                elementWriter.Begin(page);		// Begin writing to this page

                // ----------------------------------------------------------
                // Add JPEG image to the file
                Image image = Image.Create(document.GetSDFDoc(), inputImagePath);
                Element element = elementBuilder.CreateImage(image, new Matrix2D(200, 0, 0, 250, 50, 500));
                elementWriter.WritePlacedElement(element);
                elementWriter.End();	// Finish writing to the page
                document.PagePushFront(page);

                // Take a snapshot after making changes, so that we can redo later (after undoing first).
                ResultSnapshot snapshot1 = undoManager.TakeSnapshot();
                if (snapshot1.PreviousState().Equals(snapshot0State))
                {
                    WriteLine("snapshot1 previous state equals snapshot0State; previous state is correct");
                }

                DocSnapshot snapshot1State = snapshot1.CurrentState();

                await document.SaveAsync(outputPath, SDFDocSaveOptions.e_incremental);
                await AddFileToOutputList(outputPath).ConfigureAwait(false);

                if (undoManager.CanUndo())
                {
                    ResultSnapshot undoSnapshot = undoManager.Undo();

                    await document.SaveAsync(outputUndoPath, SDFDocSaveOptions.e_incremental);
                    await AddFileToOutputList(outputUndoPath).ConfigureAwait(false);

                    DocSnapshot undoSnapshotState = undoSnapshot.CurrentState();
                    if (undoSnapshotState.Equals(snapshot0State))
                    {
                        WriteLine("undoSnapshotState equals snapshot0State; undo was successful");
                    }

                    if (undoManager.CanRedo())
                    {
                        ResultSnapshot redoSnapshot = undoManager.Redo();

                        await document.SaveAsync(outputRedoPath, SDFDocSaveOptions.e_incremental);
                        await AddFileToOutputList(outputRedoPath).ConfigureAwait(false);

                        if (redoSnapshot.PreviousState().Equals(undoSnapshotState))
                        {
                            WriteLine("redoSnapshot previous state equals undoSnapshotState; previous state is correct");
                        }

                        DocSnapshot redoSnapshotState = redoSnapshot.CurrentState();
                        if (redoSnapshotState.Equals(snapshot1State))
                        {
                            WriteLine("snapshot1 and redoSnapshot are equal; redo was successful");
                        }
                    }
                    else
                    {
                        WriteLine("Problem encountered - cannot redo.");
                    }
                }
                else
                {
                    WriteLine("Problem encountered - cannot undo.");
                }

            }
            catch (Exception e)
            {
                WriteLine(GetExceptionMessage(e));
                error = true;
            }

            return error;
        }
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.apryse.com/uwp/get-started/samples/undoredotest.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
