Click here to Skip to main content
15,867,968 members
Articles / Programming Languages / C#
Tip/Trick

How to Limit TextBox Entries to Decimal or Integer Values in Windows Forms with C#

Rate me:
Please Sign up or sign in to vote.
3.29/5 (22 votes)
19 Nov 2014CPOL3 min read 115.1K   23   31
How to Limit TextBox Entries to Decimal or Integer Values in Windows Forms with C#

A Straightforward Way to Restrict Text Box Entries to Decimal or Integer Values

A way to "mask" entries in a Textbox so as to allow only 0..9, backspace, and at most one "." is to handle the TextBox's KeyPress() event as follows (assuming the TextBox in question is named txtbxPlatypus):

C#
private void txtbxPlatypus_KeyPress(object sender, KeyPressEventArgs args)
{
    const int BACKSPACE = 8;
    const int DECIMAL_POINT = 46;
    const int ZERO = 48;
    const int NINE = 57;
    const int NOT_FOUND = -1;

    int keyvalue = (int)args.KeyChar; // not really necessary to cast to int

    if ((keyvalue == BACKSPACE) || 
    ((keyvalue >= ZERO) && (keyvalue <= NINE))) return;
    // Allow the first (but only the first) decimal point
    if ((keyvalue == DECIMAL_POINT) && 
    (txtbxPlatypus.Text.IndexOf(".") == NOT_FOUND)) return;
    // Allow nothing else
    args.Handled = true;
}

There are probably other, better (more elegant and robust) ways to do this, but this works for me / meets my tough standards; YMMV.

Even Easier to Restrict To Integer Values

It's even easier to restrict the entry to just integer values:

C#
private void txtbxPteradactyl_KeyPress(object sender, KeyPressEventArgs args)
{
    const int BACKSPACE = 8;
    const int ZERO = 48;
    const int NINE = 57;

    int keyvalue = args.KeyChar;

    if ((keyvalue == BACKSPACE) || 
    ((keyvalue >= ZERO) && (keyvalue <= NINE))) return;
    // Allow nothing else
    args.Handled = true;
}

DRY by Learning to Delegate

Better yet, rather than adding this code to every TextBox's KeyPress event, you can attach other TextBoxes requiring the same filtering to the one event handler. What, though, about the explicit reference to the name of the TextBox in the handler to restrict to decimal values? Never fear: you can change this line of code:

C#
if ((keyvalue == DECIMAL_POINT) && 
(txtbxPlatypus.Text.IndexOf(".") == NOT_FOUND)) return;

to this:

C#
if ((keyvalue == DECIMAL_POINT) && 
((sender as TextBox).Text.IndexOf(".") == NOT_FOUND)) return;

That way, you can assign each TextBox's KeyPress event to the original one and, since the name of the textbox is not explicitly referenced, but instead "sender as TextBox", they will all use the same character-filtering code.

Go Global (I'm Bad, I'm Project-Wide)

Even more betterest, you can either be a fancy pants and create a control based on a TextBox, give it a KeyPress event as above, and then use that custom TextBox control OR you can declare a KeyPress handler in one place in your code, such as in a "Shareable event handlers" section you insert into a Utils class (you have added a <appname>Utils to your project, right?), like so:

C#
// Shareable event handlers; could alternately create custom classes (see http://stackoverflow.com/questions/26897909/how-can-i-share-control-specific-event-handlers-project-wide)
public static void DecimalsOnlyKeyPress(object sender, KeyPressEventArgs args)
{
    const int BACKSPACE = 8;
    const int DECIMAL_POINT = 46;
    const int ZERO = 48;
    const int NINE = 57;
    const int NOT_FOUND = -1;

    int keyvalue = args.KeyChar;

    if ((keyvalue == BACKSPACE) || ((keyvalue >= ZERO) && (keyvalue <= NINE))) return;
    // Allow the first decimal point
    if ((keyvalue == DECIMAL_POINT) && ((sender as TextBox).Text.IndexOf(".") == NOT_FOUND)) return;
    // Allow nothing else
    args.Handled = true;
}

public static void IntegersOnlyKeyPress(object sender, KeyPressEventArgs args)
{
    const int BACKSPACE = 8;
    const int ZERO = 48;
    const int NINE = 57;

    int keyvalue = args.KeyChar;

    if ((keyvalue == BACKSPACE) || ((keyvalue >= ZERO) && (keyvalue <= NINE))) return;
    // Allow nothing else
    args.Handled = true;
}
// <!-- Shareable event handlers

With that in place, you can hook up text boxes to use that event from the constructor of any form, like so:

C#
public frmDuckbill()
{
    InitializeComponent();
    // Use project-wide event handlers
    textBoxCost.KeyPress += new KeyPressEventHandler(PlatypusUtils.DecimalsOnlyKeyPress);
    textBoxDiscount.KeyPress += new KeyPressEventHandler(PlatypusUtils.DecimalsOnlyKeyPress);
    textBoxNumberOfTimesIYelledYeeHawToday.KeyPress += new KeyPressEventHandler(PlatypusUtils.IntegersOnlyKeyPress);
}

Take 5

Inspired/prodded by Jacques Bourgeois in his comment below (now I'm thinking of Cousteau, and Leadbelly singing "The Bourgeois Blues"), I rewrote my handlers to use Convert.ToBla() in the TextChanged event (TryParse, which he recommended, doesn't work for me in the .NET 3.5/Windows CE world, although it may for you, and be a better choice). At any rate, here is the new and doubtless improved approach:

C#
public static void DecimalsOnlyTextChanged(object sender, EventArgs args)
{
    TextBox txtbx = (sender as TextBox);
    String candidateText = txtbx.Text;
    // Retreat! Attempting to convert an empty string is not pretty
    if (String.IsNullOrEmpty(candidateText)) return;
    try
    {
        Convert.ToDecimal(candidateText);
    }
    catch (Exception)
    {
        String allButTheLast = candidateText.Substring(0, candidateText.Length - 1);
        txtbx.Text = allButTheLast;
        txtbx.Select(txtbx.Text.Length, 0);
    }
}

public static void IntegersOnlyTextChanged(object sender, EventArgs args)
{
    TextBox txtbx = (sender as TextBox);
    String candidateText = txtbx.Text;
    if (String.IsNullOrEmpty(candidateText)) return;
    try
    {
        Convert.ToInt32(candidateText);
    }
    catch (Exception)
    {
        String allButTheLast = candidateText.Substring(0, candidateText.Length - 1);
        txtbx.Text = allButTheLast;
        txtbx.Select(txtbx.Text.Length, 0);
    }
}

Using this methodology, you could write custom Convert.ToBla() methods for your own particular/peculiar needs, such as Convert.ToPlatypus(), Convert.ToPureGold(), Convert.ToIslam(catStevens), Convert.ToCheddarCheese() or whatever. More likely, they would be things like Convert.ToPhoneNum(), Convert.ToEmailAddr(), Convert.ToURL(), &c.

Possible (If not Likely) Benefits

If you put this tip into practice, you might hear the bluebird of happiness chirping merrily away, and all your wildest dreams could come true. OTOH, the bird of paradise may fly up your nose, and it's not entirely impossible that an elephant would caress you with his toes. Do you feel lucky today?

Post Escribem

For my part, posting this has resulted in not only the Big Bird of Paradise flying up my left nostril, but a peeved pack of Pachyderms have ground me to a pitiful pulverized pulp, having pilloried and pillaged my person, apparently with profund relish (I would have preferred Grey Poupon (and I don't even like Grey Poupon all that much - das ist nicht mein Senf))!

Presumably, my appearance is a far cry from that of a Dalmation puppy at present.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Founder Across Time & Space
United States United States
I am in the process of morphing from a software developer into a portrayer of Mark Twain. My monologue (or one-man play, entitled "The Adventures of Mark Twain: As Told By Himself" and set in 1896) features Twain giving an overview of his life up till then. The performance includes the relating of interesting experiences and humorous anecdotes from Twain's boyhood and youth, his time as a riverboat pilot, his wild and woolly adventures in the Territory of Nevada and California, and experiences as a writer and world traveler, including recollections of meetings with many of the famous and powerful of the 19th century - royalty, business magnates, fellow authors, as well as intimate glimpses into his home life (his parents, siblings, wife, and children).

Peripatetic and picaresque, I have lived in eight states; specifically, besides my native California (where I was born and where I now again reside) in chronological order: New York, Montana, Alaska, Oklahoma, Wisconsin, Idaho, and Missouri.

I am also a writer of both fiction (for which I use a nom de plume, "Blackbird Crow Raven", as a nod to my Native American heritage - I am "½ Cowboy, ½ Indian") and nonfiction, including a two-volume social and cultural history of the U.S. which covers important events from 1620-2006: http://www.lulu.com/spotlight/blackbirdcraven

Comments and Discussions

 
GeneralMy vote of 1 Pin
BillWoodruff20-Nov-14 3:58
professionalBillWoodruff20-Nov-14 3:58 
GeneralRe: My vote of 1 Pin
nicktorn20-Nov-14 5:02
nicktorn20-Nov-14 5:02 
GeneralRe: My vote of 1 Pin
B. Clay Shannon20-Nov-14 5:07
professionalB. Clay Shannon20-Nov-14 5:07 
QuestionWhy not use a NumericUpDown control? Pin
wmjordan19-Nov-14 14:23
professionalwmjordan19-Nov-14 14:23 
AnswerRe: Why not use a NumericUpDown control? Pin
B. Clay Shannon19-Nov-14 14:39
professionalB. Clay Shannon19-Nov-14 14:39 
GeneralMy vote of 2 Pin
johannesnestler18-Nov-14 3:38
johannesnestler18-Nov-14 3:38 
* No localization support
* handling logic with exceptions.
* no Support for negative numbers or any other number formats (scientific Notation?)

On the plus side is clear code and funny written tip.
So bad vote is to stop other from using this limited approach.
GeneralMy vote of 3 Pin
Klaus Luedenscheidt17-Nov-14 19:06
Klaus Luedenscheidt17-Nov-14 19:06 
GeneralMy vote of 4 Pin
dmjm-h17-Nov-14 12:37
dmjm-h17-Nov-14 12:37 
GeneralMy vote of 1 Pin
Thornik15-Nov-14 2:01
Thornik15-Nov-14 2:01 
GeneralRe: My vote of 1 Pin
AORD18-Nov-14 8:00
AORD18-Nov-14 8:00 
GeneralRe: My vote of 1 Pin
Thornik18-Nov-14 8:47
Thornik18-Nov-14 8:47 
GeneralRe: My vote of 1 Pin
AORD18-Nov-14 9:47
AORD18-Nov-14 9:47 
GeneralRe: My vote of 1 Pin
Thornik18-Nov-14 10:10
Thornik18-Nov-14 10:10 
GeneralRe: My vote of 1 Pin
AORD18-Nov-14 11:03
AORD18-Nov-14 11:03 
GeneralRe: My vote of 1 Pin
Thornik18-Nov-14 13:52
Thornik18-Nov-14 13:52 
GeneralRe: My vote of 1 Pin
AORD18-Nov-14 14:48
AORD18-Nov-14 14:48 
Suggestion[My vote of 2] If you're going to derive your own control.... Pin
ozbear14-Nov-14 10:33
ozbear14-Nov-14 10:33 
QuestionI remember this... Pin
DarkChuky CR14-Nov-14 8:12
DarkChuky CR14-Nov-14 8:12 
GeneralMy vote of 1 Pin
s2bert14-Nov-14 6:22
s2bert14-Nov-14 6:22 
Questionas keyword usage. Pin
Aurimas14-Nov-14 1:15
Aurimas14-Nov-14 1:15 
GeneralMy vote of 3 Pin
Sinisa Hajnal13-Nov-14 22:37
professionalSinisa Hajnal13-Nov-14 22:37 
GeneralThanks for pointing out the comma issue! Pin
AORD18-Nov-14 8:23
AORD18-Nov-14 8:23 
GeneralRe: Thanks for pointing out the comma issue! Pin
B. Clay Shannon18-Nov-14 8:28
professionalB. Clay Shannon18-Nov-14 8:28 
GeneralRe: Thanks for pointing out the comma issue! Pin
AORD18-Nov-14 9:00
AORD18-Nov-14 9:00 
GeneralRe: Thanks for pointing out the comma issue! Pin
Sinisa Hajnal18-Nov-14 20:09
professionalSinisa Hajnal18-Nov-14 20:09 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.