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;
if ((keyvalue == BACKSPACE) ||
((keyvalue >= ZERO) && (keyvalue <= NINE))) return;
if ((keyvalue == DECIMAL_POINT) &&
(txtbxPlatypus.Text.IndexOf(".") == NOT_FOUND)) return;
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;
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 TextBox
es 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:
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;
if ((keyvalue == DECIMAL_POINT) && ((sender as TextBox).Text.IndexOf(".") == NOT_FOUND)) return;
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;
args.Handled = true;
}
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();
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;
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.