1

So I'm working on a text editor, using a menu strip as the main control area for everything. In my Edit tab I have an Undo button that is meant to undo the last word typed.

public partial class frmMain : Form
{
     Stack<string> undoList = new Stack<string>();

     private void txtMain_TextChanged(object sender, EventArgs e)
    {
        hasSaved = false;
        txtMain = (RichTextBox)sender;
        undoList.Push(txtMain.Text);
    }

    private void tsUndo_Click(object sender, EventArgs e)
    {
            undoList.Pop();           
    }
}

When I click the undo it doesn't affect anything. I'm quite new to programming so I can't see the issue. Can someone enlighten me?

Lennart
  • 9,657
  • 16
  • 68
  • 84
  • You are just removing an element from the array. You don't tell to the button to do something. – Dimitar Sep 13 '18 at 03:50
  • That would make sense, do you know what code I should use to actually make the button do what I want? – Noah Jackson Sep 13 '18 at 03:51
  • Perhaps the define of "what I want" term can give us a clue for better code suggestion. Other than this the `sender` parameter is a reference to your button. – Dimitar Sep 13 '18 at 03:53
  • 1
    `txtMain.Text = undoList.Pop();` ? All `.Pop()` does is remove the item from `undoList` and return it to you. C# isn't psychic, I'm afraid. – ProgrammingLlama Sep 13 '18 at 04:01
  • Sorry, I haven't used Stacks before so I didn't realise this before. So what I'm trying to do is have the undo button remove the last word typed from the textbox. As far as I understand, the stack is simply storing the states of the textbox. Im not sure how to then remove the last type word. – Noah Jackson Sep 13 '18 at 04:11
  • 1
    TextChanged is the wrong event to hook into - you are going to cache each letter as an UnDo item with no way to tell which ones go together to make a word/sentence/entry/unit – Ňɏssa Pøngjǣrdenlarp Sep 13 '18 at 04:28
  • 1
    Possible duplicate of [How to implement good and efficient undo/redo functionality for a TextBox](https://stackoverflow.com/questions/597792/how-to-implement-good-and-efficient-undo-redo-functionality-for-a-textbox) – Access Denied Sep 13 '18 at 05:59

1 Answers1

1

I will get few lines of your question and explain it to you:

Stack<string> undoList = new Stack<string>(); //Creates new EMPTY Stack
undoList.Push(txtMain.Text); //Add object to the top of the Stack
undoList.Pop(); //Removes object that is on top of the Stack

So now you have TextBox and when you type something textbox.Text property changes on it's own (not you affecting it). Then you created event that will "also" besides changing text property Push() old text to your Stack on the top.

Now after text change you "have" (you do not have i will explain it later) your string on top of stack and inside your textbox

Now when you press your Undo button you need to do two things.

  • Set textBox.Text property to top object in stack
  • Delete top object in stack

Currently what you were doing is just second thing:

undoList.Pop();

But what you forgot to type before that is:

textBox1.Text = undoList.Pop();

This way you will set Text property AND delete object on top of stack.

Now let's get back you my you do not have i will explain it later.

I have said this since txtMain_TextChanged is fired AFTER text is changed.

So when you get txtMain.Text after text is changed, you will get new value instead of old one.

Also you will update your old text every time you type 1 character.

Solution to this is to use Enter event

private void textBox1_Enter(object sender, EventArgs e)
{
    //it fires only when you enter textbox with mouse click/tab/etc
    //Here add your OLD VALUE to top  of stack
}
Aleksa Ristic
  • 2,394
  • 3
  • 23
  • 54