Issue with UndoRecord.StartCustomRecord in VSTO add-in: Undo stack breaks after bullet/numbering
I am using UndoRecord.StartCustomRecord
in Microsoft.Office.Interop.Word to create custom undo records in my VSTO add-in. However, I’ve encountered some unexpected behavior that makes the Word undo stack unusable.
(I put the same question on Stackoverflow as well and got no answer, so posting the question here too.)
Here’s what I did:
- From a button click, I performed a Find and Replace operation and applied styles using the
set_Style()
method. - These actions were wrapped inside
UndoRecord.StartCustomRecord
andUndoRecord.EndCustomRecord
.
Issue: When I try to perform these custom actions after adding bullets or numbering, my custom undo record does not appear in the Undo stack as expected. Instead:
- The “Replace All” operation gets unfolded (treated as a separate undo steps rather than a single custom action).
- I can no longer undo actions that occurred before my custom action execution.
This essentially breaks the Undo stack.
Code snippet I used:Here’s what I did:
- From a button click, I performed a Find and Replace operation and applied styles using the
set_Style()
method. - These actions were wrapped inside
UndoRecord.StartCustomRecord
andUndoRecord.EndCustomRecord
.
Issue: When I try to perform these custom actions after adding bullets or numbering, my custom undo record does not appear in the Undo stack as expected. Instead:
- The “Replace All” operation gets unfolded (treated as a separate undo steps rather than a single custom action).
- I can no longer undo actions that occurred before my custom action execution.
This essentially breaks the Undo stack.
Code snippet I used:
Word.Range currentRange = Globals.ThisAddIn.Application.Selection.Range;
var application = Globals.ThisAddIn.Application;
var document = application.ActiveDocument;
this.undoRecord = application.UndoRecord;
this.undoRecord.StartCustomRecord("MyRecord");
string replacementText = "";
Word.Find find = currentRange.Find;
find.ClearFormatting();
find.Replacement.ClearFormatting();
find.Text = "^p"; // Paragraph break
find.Replacement.Text = replacementText;
find.Forward = true;
find.Wrap = Word.WdFindWrap.wdFindStop;
find.Format = false;
find.MatchCase = false;
find.MatchWholeWord = false;
find.MatchWildcards = false;
find.Execute(Replace: Word.WdReplace.wdReplaceAll);
foreach (Word.Paragraph paragraph in document.Paragraphs)
{
paragraph.Range.set_Style(Microsoft.Office.Interop.Word.WdBuiltinStyle.wdStyleEmphasis);
}
this.undoRecord.EndCustomRecord();
I made a sample project in GitHub to recreate this issue. You can build the GitHub sample and try to recreate the issue. Following are the recreation steps.
- Add some paragraphs to the document
- Add a number or bullet from Numbering menu.
- Click on the top button in my VSTO plugin.
- Custom undo action doesn't reflect properly in Undo stack
- If the same actions were done to a document without bullets or numbering, undo stack will be unharmed and will work properly.
Am I using UndoRecord.StartCustomRecord
incorrectly, or is this a limitation/bug in Word’s undo stack? How should I correctly implement custom undo records in this scenario?