5

I have a very bizarre problem with the TextChanged event in a multiline TextBox (WinForms). it appears that the event fires twice under certain circumstances.

This complete code demonstrates the issue:

public partial class TextChangedTest : Form
{
    public TextChangedTest()
    {
        InitializeComponent();
    }

    private void TextChangedTest_Load(object sender, EventArgs e)
    {
        TextBox tb = new TextBox();
        //Remove the following line and the code behaves as expected
        tb.Multiline = true;
        this.Controls.Add(tb);
        tb.TextChanged += new EventHandler(tb_TextChanged);
    }
    private void tb_TextChanged(object sender,EventArgs e)
    {
        //Need to validate and use the new text here.
        //For testing, just use a MessageBox
        MessageBox.Show("Handler fired");
    }
}

If you now type a character in the TextBox, the event fires. Correct behaviour.

If you delete the character, the event fires once. Correct behaviour.

If you delete the character with backspace, the event fires once. Correct behaviour.

If you delete the character by selecting it and pressing Delete, the event fires once. Correct behaviour.

However

If you select the character and type another character, the event fires twice, once after the text box is cleared (look at the textbox when the first event fires) and once when the character is added. This behaviour is nonsense, if understandable.

This only happens when the Multiline property is set (which I am using to resize the TextBox). It just took me 5 hours to work that out!

My problem is that I have to validate each character in the TextChanged event, and I get invalid results.

Does anyone have any ideas?

I could possibly use the Keypress event, but I would need to do a lot of recoding to do that.

Blind Fury
  • 469
  • 3
  • 15
  • Just FYI, I was able to replaicate in .NET FW 4.5 VS2012. – deepee1 Feb 04 '15 at 21:35
  • @deepee1 Thanks. Not just me being thick again... – Blind Fury Feb 04 '15 at 21:37
  • 1
    The textbox is actually doing two things when you select some text then press a key to overwrite. It deletes the text (First text changed event) then it inserts the new text (Second text changed event). You can see this if you change the message box to display the text of the textbox on each change. Not sure why it does this with the multiline. You could look through the source http://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/TextBox.cs,577a143ad3bbfb97, – MisterXero Feb 04 '15 at 21:39
  • @MisterXero Yep. I worked that out for myself (it is in the question). You can see that the TextBox is blank while the first MessageBox is displayed. Makes no sense to me that it only does it for multiline, though. – Blind Fury Feb 04 '15 at 21:44
  • The `TextChanged` event is fired for each [EN_CHANGE](https://msdn.microsoft.com/en-us/library/windows/desktop/bb761676%28v=vs.85%29.aspx) message sent to that textbox, so the "problem" is Windows, not .NET WinForms. – CodeCaster Feb 04 '15 at 21:45
  • But why only with Multiline? – Blind Fury Feb 04 '15 at 21:47
  • 1
    I don't know. [It's not a new issue anyway, according to this exactly 10 year old post](http://www.tech-archive.net/Archive/VC/microsoft.public.vc.mfc/2005-02/0643.html). – CodeCaster Feb 04 '15 at 21:53

1 Answers1

1

The workaround for my particular case is even more bizarre.

I needed the Textbox to have a specific size, but the height cannot be changed unless it is multiline.

The following, however, works for me in my little world:

    tb.Multiline = true;
    tb.Size = new Size(x,y);
    tb.Multiline = false;
    this.Controls.Add(tb);
    tb.TextChanged += new EventHandler(tb_TextChanged);

Solution found at http://en.code-bude.net/tag/c-textbox-height-resize/

Doesn't resolve the underlying problem, though.

Blind Fury
  • 469
  • 3
  • 15