Search code examples
c#wpftextboxtextchanged

modify Text in TextBox before Text is displayed


I want to modify the Text, that is typed in the TextBox, before it is displayed, without looking on the Text, that is already typed.

Example: xaml:

<TextBox x:Name="tb" TextChanged="tb_TextChanged">
    my long text
</TextBox>

c#:

private void tb_TextChanged(object sender, TextChangedEventArgs e)
{
    TextBox tb = sender as TextBox;

    if (tb != null)
    {
        //save caretIndex
        int caretIndex = tb.CaretIndex;

        //modify Text //can be any modification
        //vvvvvvvvvvv Lines that I'm talking about

        tb.Text.ToLower(); //or: tb.Text.ToLower(); etc.

        char[] notAllowedChars = new char[] {'/t', '~', '#'}; //any other
        foreach (char c in notAllowedChars)
        {
            tb.Text = tb.Text.Replace(c, '_'); //replace unwanted characters
        }

        //^^^^^^^^^^^^ these lines modify the whole text

        //restore caretIndex
        tb.CaretIndex = caretIndex;
    }
}

In that example, the whole Text is going to be modified. But all of the other characters are already modified. So I don't want to go through them again. I want only to modify the changed text before it gets inserted.

I'm talking of 100.000+ Characters. That means, that the looking up all characters causes an unwanted performance issue.

Is there any solution or is it an impossible demand.


Solution

  • You can look at the TextChangedEventArgs to see the changes, and then modify the text again...here is some starting code:

    private bool m_bInTextChanged;
    private void tb_TextChanged(object sender, TextChangedEventArgs e)
    {
        if (m_bInTextChanged)
            return;
    
        m_bInTextChanged = true;
    
        TextBox tb = sender as TextBox;
    
        if (tb != null)
        {
            //save caretIndex
            int caretIndex = tb.CaretIndex;
    
            if (e.Changes.Any())
            {
                var addedchanges = e.Changes.Where(tc => tc.AddedLength > 0);
    
                foreach (var added in addedchanges)
                {
                    string stringchanged = tb.Text.Substring(added.Offset, added.AddedLength);
    
                    tb.Select(added.Offset, added.AddedLength);
    
                    tb.SelectedText = stringchanged.ToLower();
                }
            }
    
            //restore caretIndex
            tb.CaretIndex = caretIndex;
        }
    
        m_bInTextChanged = false;
    }