How to Undo and Redo in C# (Rich Text Box)
Asked Answered
S

2

6

I've been trying to get undo and redo working in my text editor for about 3 days now. It's doing my head in.

I have a text box (named richTextBoxPrintCtrl1), which I would like to be able to undo and *redo *(word by word).

So if I click the undo button, it undoes the last word. And if I then clicked the redo button, it redoes the last word.

Could somebody help me get this working?

richTextBoxPrintCtrl1.Undo(); doesn't work very well. It deletes everything typed in the text box.

Thanks in advance for your help.

I know this question has been asked many times before, but I can't get it working using the information from the questions I've browsed here on SO.

Scrip answered 2/4, 2013 at 19:24 Comment(6)
I'm new to programming so forgive me if I'm being stupid.Scrip
There are several previous questions regarding this topic. You should do a search on StackOverflow for it. This one, for example #8026426Omnifarious
As I said, I have searched various sources (including SO) but cannot find one which I can understand/implement.Scrip
Then it would help if you posted code that showed what you've been able to do so far. As the other answers say, you have to implement your own custom undo using a stack each time the TextChanged event is fired and then pop the stack each time undo is called.Omnifarious
The thing is I haven't been able to get ANY type of undo working (besides richTextBoxPrintCtrl1.Undo();).Scrip
Peculiar. Undo and redo with ctrl+z and ctrl+y simply, uh, work, in a rich text box. The overall break in what is considered one edit seems to be caret movement.Unfinished
O
7

Ok, I'll post some code to help you get started. first you need to listen for the TextChanged event.

textBox1.TextChanged += new EventHandler(textBox1_TextChanged);

and you need to declare a stack in the class

 Stack<string> undoList = new Stack<string>();

In the text changed handler, you need to add the contents of the textbox to the stack

 void textBox1_TextChanged(object sender, EventArgs e)
    {
        undoList.Push(textBox1.Text);
    }

Then you need to handle the undo, so you could simply use CTRL-Z

 textBox1.KeyDown += new KeyEventHandler(textBox1_KeyDown);

void textBox1_KeyDown(object sender, KeyEventArgs e)
    {
         if(e.KeyCode == Keys.Z && (e.Control)) {
             textBox1.Text = undoList.Pop();
         }
    }
Omnifarious answered 2/4, 2013 at 20:9 Comment(5)
you can also check if undoList.Count > 0 and make the textbox's text an empty string to avoid an empty stack error if you undo all the way to the beginning.Ciliary
I found one problem with this code. maybe I did it wrong but at the event handler I found that I have to pop the textbox list twice because. the texchanged function is being trigger as wellSchlieren
I Found something interesting with the code. If I apply this to a button, such as a redo button. I have to pop it twice because the textchanged is being triggeredSchlieren
This does not work : the Push add the last text so it does not do the undo when pop... and when the text is assigned in KeyDown, the TextChanged event is called.Fanchan
This does not work : the Push add the last text so it does not do the undo when pop... and when the text is assigned in KeyDown, the TextChanged event is called. How to implement good and efficient undo/redo functionality for a TextBox (My attempt is here)Fanchan
B
5

You can have the RichTextBox build the undo stack for you word by word, plus keep track of the caret position, by handling one of the KeyDown-, KeyPress- or KeyUp events like this:

 private void rtb_KeyDown(object sender, KeyEventArgs e)
    {
        // Trick to build undo stack word by word
        RichTextBox rtb = (RichTextBox)sender;
        if (e.KeyCode == Keys.Space)
        {
            this.SuspendLayout();
            rtb.Undo();
            rtb.Redo();
            this.ResumeLayout();
        }
        // eztnap
    }

Since the RichTextBox does the job for you, you just have to call rtb.Undo() or rtb.Redo() from wherever you need to.

Bogbean answered 7/10, 2014 at 14:23 Comment(3)
note that there are other white spaces you'd might want to consider (like tab, etc)Jabiru
Any reason you know why I couldn't use this with JSON, to be able to undo/redo through the states (so a LOT more words per instance?)Motte
If you use an Undo menu with ctrl+z as the keyboard shortcut. Put rtb.Undo() inside it's Click event for ctrl+z to work in stack.Ectogenous

© 2022 - 2024 — McMap. All rights reserved.