7

While trying to do something a bit more complicated, I ran across a behavior I don't quite understand.

Assume the following code below handling the textChanged event.

 private void textChanged(object sender, TextChangedEventArgs e)
    {
        TextBox current = sender as TextBox;
        current.Text = current.Text + "+";
    }

Now, typing a character in the textbox (say, A) will result in the event getting tripped twice (adding two '+'s) with the final text displayed being just A+.

My two questions are, why is the event hit just twice? And why does only the first run through the event actually set the text of the textbox?

Thanks in advance!

Erik Kerber
  • 5,646
  • 7
  • 38
  • 56
  • 2
    why does a question that seems to make little sense have 3 upvotes in less than 4 minutes? I don't get it.... – Mitch Wheat May 24 '10 at 15:55
  • ...went up to 5 votes and then back to 3? hmmmmm... – Mitch Wheat May 24 '10 at 16:00
  • 1
    The event TextBox.TextChanged is raised when TextBox.Text has changed. The sample code, however, changes the text during this notification which should result in a further raising of TextChanged which will then result in a new change of Text which will... --> Endless recursion.
    I did not knew that this special case is explicitly handled by the TextBox class - the described effect will NOT occur. Instead, TextChanged will only be raised once. I learned something through this question and therefore upvoted it.
    – Matthias May 24 '10 at 16:10
  • 1
    Care to explain what part doesn't make sense? Or at least offer clarification? winSharp93 seemed to nail it. – Erik Kerber May 24 '10 at 16:11

1 Answers1

7

Well - setting the Text property while it is being changed / while it has just changed seems to be caught by the TextBox class explicitly:

Just use the Reflector to look inside TextBox.OnTextPropertyChanged (shortened):

TextBox box = (TextBox) d;
if (!box._isInsideTextContentChange)
{
    string newValue = (string) e.NewValue;
    //...
    box._isInsideTextContentChange = true;
    try
    {
        using (box.TextSelectionInternal.DeclareChangeBlock())
        {
           //...
        } //Probably raises TextChanged here
    }
    finally
    {
        box._isInsideTextContentChange = false;
    }
    //...
}

The field _isInsideTextContentChange is set to true before the TextChanged event gets raised. When changing the Text property again, the TextChanged event thus is not raised again.

Therefore: Feature ;-)

Matthias
  • 12,053
  • 4
  • 49
  • 91