Search code examples
c#wpfxamltextboxconverters

Why does my WPF converter “miss” the last character in the TextBox?


I’m building a WPF application using Visual Studio 2019. One of the views of this application has a TextBox inside of it, which is binded to a property of its DataContext. The code related to the TextBox is this:

<TextBox x:Name="Alpha" Text="{Binding Model.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, 
                              ValidatesOnDataErrors=True, Converter={StaticResource ToUpper}}" />

As you can guess, the ToUpper converter makes the text inside the TextBox uppercase. When I write something inside the TextBox, I see it’s uppercase, so the converter seems to work. So far so good, but the problem is that the last character seems to be “missing” during the conversion. I say that because when I write something in the TextBox, text that is made uppercase by the converter, in the code-behind of the view:

private void OnLoaded(object sender, RoutedEventArgs e)
   Alpha.KeyDown += Alpha_KeyDown;
}

private void Alpha_KeyDown(object sender, System.Windows.Input.KeyEventArgs e) {
   if (e.Key == Key.Return) {
      var a = Alpha.text;
   }
}

I find that the a variable stores the exact same text of the TextBox, but with the last character lowercase. For example, if I write “abcde” inside the TextBox, the converter makes it uppercase and the view renders “ABCDE”, but a is set to “ABCDe”.

The Convert() method of the converter is this:

public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
   var myString = value as string;
   return text != null ? text.ToUpper() : "No text";
}

Why does this happen?


Solution

  • The KeyDown event is triggered before the Text property changes. The following can make it clear:

    private void Alpha_KeyDown(object sender, KeyEventArgs e)
    {
     if (e.Key == Key.Return)
     {
      Debug.WriteLine("After return: " + Alpha.Text);
     }
     else
     {
      Debug.WriteLine(Alpha.Text + e.Key.ToString().ToUpper());
     }
    }
    

    So, by this time Alpha.Text haven't updated with the new key and hence not converted.