Skip to content


Making TextBox Numbers Only for Windows Phone 7

 

I wanted to make a simple application for Windows Phone 7 that required a number of TextBox controls to only accept numeric input.  Some would be able to take decimals, and others would not.

Sounds easy correct?  It really isn’t as straight-forward as I would want it to be, or as easy as it is in ASP or Windows Forms programming or WPF. 

The reason it is not as easy you think it would be is that the framework for Windows Phone 7 does not, at this time contain a way of the developers to distinguish between the special keys (the ones you get on a normal keyboard using the Shift key) and the numbers that would, on a normal keyboard, be under them.  I think that, at some level, they are using the same code and passing a Shift key identifier to the control so that it knows what character to produce, but at the level we access it, there does not seem to be anyway to determine the use of that unseen Shift key. 

What this does is that if you trap for the #, you will also trap and stop the entry of the number 3.  This has caused developers some difficulty when trying to control the user entries.

There is a way to do it though.  It is actually pretty easy, there are a few steps and I have demonstrated them below.

Step 1 – Choose the correct InputScope

The one that I found that worked the best was the Telephone InputScope.  This one had all the digits and the least number of extra keys that we will have to block.  It also does not have any button that would allow the user to go to another InputScope.

I made a simple method that I could then call once for each of the TextBox controls I wanted to restrict input to numbers only:

Then I called each one for the applicable TextBox controls:

Now when I run the application, and set focus to one of the text boxes, I get the numeric InputScope panel I want:

Step 2 – Handle Invalid Characters

The only problem with this InputScope is that there are a few invalid characters for a numeric control.  The obvious ones are the “*“;  “+” (hold the 0 key);  “,” and the “#“.  There are also some keys that are not obvious at first.  These appear when you hold down the decimal “.” key:

You are then presented with four more keys that are invalid for a numeric TextBox: “(“; “)“; “x“; and “-“.

In order to trap and mask the TextBox control from these keys we need a method that will allow for the invalid characters to be removed.  Since we already know about the PlatformKeyCode’s inability to distinguish between certain keys and their decimal equivalents, we have to do it on the KeyUp event instead of the KeyDown event. 

We also have to take into account that for some fields we want to allow decimals, but for others, we want numbers only.  In order to solve both problems with the least amount of code, we create a method that will be called by event handler methods:

Now, as mentioned before, we need to create handler methods to call this method that removes the invalid characters from the TextBox control:

Step 3 – Call the Code from the Controls

Now, all that is left is to set the handlers to the correct controls and we are done!

First, for controls that are NUMBERS ONLY, no decimals, the process is easy, simply call the appropriate event handler (in this case, numericOnlyTextBox_KeyUp) from the KeyUp event:

This will ensure that there are no decimals ever seen as the decimals are placed into the array holding the invalid characters and removed when found.

The only problem I found was that when I allowed decimals to be entered into the TextBox control, the user could add as many as they wanted.  This made the numbers invalid and could cause errors in my code, so I had to create a method that would be called on the KeyDown event for TextBox controls that accepted decimals:

With TextBox controls that you want to allow a decimal in, you will have to call both this KeyDown event handler and a different KeyUp event handler:

Now, we have it!  A quick and flexible way to handle numeric entry into TextBox controls.

Hope this helps,

Atley

Posted in C#, Windows Phone 7.

Tagged with , .


32 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

  1. Brent says

    Atley,

    Thanks for the illustrating this. I was wondering how to force numbers on a TextBox and you answered my question.

    The other question I have is how to get the SIP to show numbers rather than letters on the default keyboard when entering the TextBox. It would save the user an extra keystroke and some confusion when trying to type a number in a TextBox where they are expecting to enter a number (but instead they see letters by default). Is this possible?

    Thanks,
    Brent

    • Atley says

      Yes, you can have the SIP to show the number side of the default keyboard first by choosing the Digit InputScope. This will allow the user to still have access to the abcd key and therefore they can switch back to the letter side of the SIP.

      If you want to only allow numbers in the control, you should use the Telephone InputScope as it does not offer the user the option of going back to a letter keyboard. This saves you from having to trap for all of the letters as well as a lot more special characters.

  2. Brent says

    Awesome. Thanks for answering my question.

  3. Risaso says

    hello thanks for the article.

  4. v says

    Thanks for that awesome posting. It saved MUCH time :-)

  5. Julian Mathews says

    Great!

  6. Chintz says

    Working great… Thank you so much

  7. Anonymous says

    This was a excellent piece of writing. Your article is useful,thank you.

  8. Marolt says

    Nice post. Thank You for taking the time to share it with us.

  9. Richard Davison says

    Some small improvments:
    * uses a foreach instead of for loop, simpler and faster ;)
    * only allows the user to insert one decimal

    Hope you like it:

    private void MaskNumericInput(TextBox textBoxControl, bool allowDecimals)
    {
    string[] invalidChars = { “*”, “#”, “.”, “(“, “)”, “x”, “-”, “+”, ” “, “@” };

    if(!allowDecimals)
    {
    invalidChars[invalidChars.Length - 1] = “,”;
    }

    foreach (string s in invalidChars)
    {
    textBoxControl.Text = textBoxControl.Text.Replace(s, “”);
    }

    int firstDotIndex = textBoxControl.Text.IndexOf(‘,’);
    int lastDotIndex = textBoxControl.Text.LastIndexOf(‘,’);

    if (firstDotIndex != lastDotIndex)
    {
    textBoxControl.Text = textBoxControl.Text.Remove(lastDotIndex);
    }

    textBoxControl.SelectionStart = textBoxControl.Text.Length;
    }

    • Atley says

      Yes, it can definitely be done that way as well. Thanks!

    • Cory Fowler says

      @Richard – You would not want to use a foreach to do iterative processes on the phone. The Call to GetEnumorator() which the foreach loop does internally yields a slower performance over using the for statement.

      If you start using a foreach, people will start talking about using Linq which opens open another large ball of wax around Garbage Collection.

      You will want to consider performance impacts when creating your phone applications as it will directly relate to your customer satisfaction when they use the application you have built.

      • Atley says

        @Cory Thanks for pointing that out! Great point!

  10. XeeLee says

    This is the modification of the above code that define the valid symbols in opposite to the above version that defines the invalid characters. Might suit better in some cases. The code below allows to enter only 0 or 1 and can be modified to include more valid characters in the if condition brackets.

    for (int i = 0; i < textBoxControl.Text.Length; i++)
    {
    if (!textBoxControl.Text[i].Equals('0') && !textBoxControl.Text[i].Equals('1'))
    {
    textBoxControl.Text = textBoxControl.Text.Remove(i);
    }
    }

    • Atley says

      It is one way to do it, but I think that for the purposes of this situation, the multiple if statement would be a bit too verbose.

  11. Brian says

    Very well done. Thanks for writing this!

  12. Martin says

    What if someone from a different country tries to use it which has for example , instead of . ? It sounds like this works “only” one way and I can’t use a Globalization that easy?

    • Atley says

      That is a good point… I will look at changing the base methods to include globalization.

      Thanks for the suggestion!!!

  13. Martin says

    I need to add this to the code to use the Telephone Keyboard for each TextBox, right?
    private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
    {
    SetControls();
    }

    Btw. isn’t there something better to use Numbers than the Telephone Keyboard? :)
    I wonder why I can use .Numbers but then it shows it not as intended like with the Telephone Keys…

    Could you maybe also attach the Source for this example?

    Thanks for this :)

  14. ChrisWue says

    You do block the second decimal point in the KeyDown event, why don’t you just also block all invalid characters there instead of removing them from the input in the KeyUp? I’m not a w7p developer, so there might be some non-obvious problem. Just curious.

  15. Harald says

    Use new InputScope “Digits” and sjekk only for ” ” and “.” as illegal

  16. Maikel van Houtum says

    Just simply add InputScope=”TelephoneNumber” to your xaml file

    • Atley says

      You will still have to deal with the extra characters that are allowed from that InputScope. It would slightly change the code needed.

  17. Tyler Flemming says

    Awesome, thanks for the learning experience.

  18. Raship Saiyed says

    private void SetInputScope(TextBox textBoxControl)
    {
    InputScopeNameValue digitsInputNameValue = InputScopeNameValue.Digits;
    textBoxControl.InputScope = new InputScope()
    {
    Names = {new InputScopeName() {NameValue = digitsInputNameValue }}
    };

    }

    Here the method i used is same, just slight modification, Instead of InputScopeNameValue.TelephoneNumber i have used Digits, by which only digits will display which will allow decimal values to be entered. Hope it helps.

    • Atley says

      Raship,

      Digits and TelephoneNumber currently bring up the same SIP, so both are valid choices.

  19. Kuldeep Thakur says

    Hi,

    I was reading your article and I would like to appreciate you for making it very simple and understandable. This article gives me a basic idea of TextBox control in widows phone development.

    Thanks for wonderful post it really helpful for beginner as well as developer.

  20. LZH says

    great, this is just what i am looking for.

    however is there a solution to prevent user from pasting invalid value into the textbox?

    • Atley says

      You could put a check for invalid values in the TextChanged event, but that would create too many checks. You would have to put a check on the LostFocus event of the TextBox in order to properly trap for pasted values. You would also want to ensure that this check would be performed on navigation to be certain that there was no chance of an invalid value slipping in.

  21. KS says

    hi, is there a way where we can replace the clear text with “*” similar to password?

    thks

  22. Paul S says

    I use InputScope=”Number” throughout my project when I need numeric input. It’s easier to set up – the only non-decimal keys you need to handle are the comma and the hyphen – and is less cluttered with unneeded keys.

    Documented here (WP7): http://msdn.microsoft.com/en-us/library/system.windows.input.inputscopenamevalue(v=vs.95).aspx
    (Haven’t had a chance to test it on WP8 yet but I assume it would work.)

    • Atley says

      Sorry for the late reply, yes, I use that too, but it didn’t exist in Windows Phone 7 when that article was written. I do agree that you can use that and slim down the code a little bit. Thanks for the feedback!



Some HTML is OK

or, reply to this post via trackback.