Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

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

0.00/5 (No votes)
19 Nov 2014 5  
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):

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:

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:

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

to this:

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 Utils to your project, right?), like so:

// 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:

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:

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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here