locked
XAML TextBox CharacterCasing and Validation on KeyDown RRS feed

  • Question

  • Ideally, I need to validate key input as it is being typed rather than on TextChanged and UpperCase when appropriate.

    The XAML textbox does not have CharacterCasing is there another method to achieve this.

    I can achieve this in the KeyDown event but I also need to allow other characters, * (asterisk) for example. The keycode for * on my keyboard is "Number8". Even if I track the state of the shift key this is not a totally correct solution since I presume * may be on a different key on some keyboards.

    Is there any way of finding out the actual character that has been generated.

    Any help will be gratefully received.

    Wednesday, November 27, 2013 7:04 PM

Answers

  • Hi Ted,

    Sorry there is no API in TextBox can help with CharacterCasing, but we can use binding to do the same thing. I'll help with achieve the CharacterCasing function and you can validate the input content later by your code.

    For instance I have a TextBox:

            <TextBox x:Name="tb" 
                     SelectionStart="{Binding ElementName=tb, Path=Text, Converter={StaticResource SelectPositionConvert } }" 
                     Text="{Binding ElementName=tb, Path=Text, Converter={StaticResource UpperCaseConvert}}" 
                     Margin="210,541,439,175" />

    I can do a convert(UpperCase) while binding the Text to itself, and also set the position of the cursor in TextBox by following binding code:

        public class UpperCaseConvert : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, string language)
            {
                return value.ToString().ToUpper();
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, string language)
            {
                throw new NotImplementedException();
            }
        }
    
        public class SelectPositionConvert : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, string language)
            {
                return value.ToString().Length;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, string language)
            {
                throw new NotImplementedException();
            }
        }

    --James


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    • Marked as answer by Ted Weston Thursday, November 28, 2013 10:29 AM
    Thursday, November 28, 2013 2:07 AM
    Moderator

All replies

  • Hi Ted,

    Sorry there is no API in TextBox can help with CharacterCasing, but we can use binding to do the same thing. I'll help with achieve the CharacterCasing function and you can validate the input content later by your code.

    For instance I have a TextBox:

            <TextBox x:Name="tb" 
                     SelectionStart="{Binding ElementName=tb, Path=Text, Converter={StaticResource SelectPositionConvert } }" 
                     Text="{Binding ElementName=tb, Path=Text, Converter={StaticResource UpperCaseConvert}}" 
                     Margin="210,541,439,175" />

    I can do a convert(UpperCase) while binding the Text to itself, and also set the position of the cursor in TextBox by following binding code:

        public class UpperCaseConvert : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, string language)
            {
                return value.ToString().ToUpper();
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, string language)
            {
                throw new NotImplementedException();
            }
        }
    
        public class SelectPositionConvert : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, string language)
            {
                return value.ToString().Length;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, string language)
            {
                throw new NotImplementedException();
            }
        }

    --James


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    • Marked as answer by Ted Weston Thursday, November 28, 2013 10:29 AM
    Thursday, November 28, 2013 2:07 AM
    Moderator
  • Thank you James your solution works very well and it's been very instructive on the power of binding in this way.

    I had to add some further code to UpperCaseConvert to perform some validation, which works fine. After posting my question I continued to research my problem and came up with another solution using code. I'll post this in the next day or so.

    Thanks once again.

    Thursday, November 28, 2013 10:37 AM
  • Following my earlier reply, here's the code to achieve character casing and keystroke-by-keystroke validation. I'm deeply indebted to Charles Petzold and his Programming for Windows - Writing Windows 8 Apps with C# and XAML. It takes some finding sometimes but invariably he has the answer! 

    The main player in this is the Window.Current.CoreWindow.CharacterReceived event. I don't want to get this event for every character received, only when the text box of interest has focus, so the event is added in the text box GotFocus event and removed in the LostFocus event. Of course a KeyDown event in the text box needs to be handled otherwise you will get 2 characters for every key stroke.

    The code looks like this:

    //Add the event when text box gets focus private void textBoxLetters_GotFocus(object sender, RoutedEventArgs e) { Window.Current.CoreWindow.CharacterReceived+=CoreWindow_CharacterReceived; } //Remove the event when the text box loses focus private void textBoxLetters_LostFocus(object sender, RoutedEventArgs e) { Window.Current.CoreWindow.CharacterReceived -= CoreWindow_CharacterReceived; }

            //Handle (i.e. discard) the key
            private void textBoxLetters_KeyDown(object sender, KeyRoutedEventArgs e)
            {
                e.Handled = true;
            }

            void CoreWindow_CharacterReceived(CoreWindow sender, CharacterReceivedEventArgs args)
            {
                //Convert KeyCode to char and then to string and then to upper case
                string s = ((char)args.KeyCode).ToString().ToUpper();
    
                //Do validation
                if ("*ABCDEFGHIJKLMNOPQRSTUVWXYZ.".Contains(s))
                {
                    //If character received is valid (i.e. in this example alpahbetic * or . add it to the existing text in the text box
                    textBoxLetters.Text += s;
                    textBoxLetters.SelectionStart = textBoxLetters.Text.Length;
                }
                //It seems implicit that the character is disposed of
            }
    
    James' solution works fine but it's down to choice, I suppose.


    Thursday, November 28, 2013 3:26 PM