Click here to Skip to main content
15,886,055 members
Articles / Programming Languages / C#
Article

Numeric Edit Control

Rate me:
Please Sign up or sign in to vote.
4.27/5 (30 votes)
25 Apr 20034 min read 211.7K   1.7K   61   30
A TextBox control that validates different numeric types.

NumEdit Image

Introduction

Building database data entry applications raises many questions. The one I want to discuss here is, "When should one validate user input?" Catching invalid data entry at the earliest possible point - while the user is typing - can have great advantages. Validating after entry such as during the LostFocus() event works, but you are faced with difficult choices. 1) Send the focus back if data is invalid, possibly causing the user to get "stuck" in a control or 2) Allow the focus to move with invalid data and the user must return to the invalid control to correct the problem.

With the purpose of stopping invalid data entry before it happens, let's take a look at the NumEdit Control.

Key Considerations

I wanted to be able to easily handle a variety of different .NET basic numeric data types such as various size floating point and integer types as well as Currency (internally treated as Decimal). Adding an IsDigit() check in the KeyPress event could handle much of the work, but there would be a few things missing.

First, digit-only filtering doesn't allow the decimal point or the negation "-" character. With a few changes we can allow negative numbers and a the decimal point, but the code rapidly becomes messy dealing with duplicate decimals and negative characters only in the first position.

Second, and possibly more important, is the numeric value entered. If we are working with .NET 32 bit integer values for example, then we need to stop further entry once the maximum value of an integer is typed. Otherwise we will be dealing with overflow errors.

For this reason, I chose to use the Type.Parse() method to test for valid typing. If the Parse() method throws an exception, then we know the KeyPress character is not valid and it should be canceled. This technique stops overflow errors when converting our TextBox string into numeric values. It also stops duplicate decimals as well as duplicate negation ("-") characters.

Last is pasting. Using IsDigit() in the KeyPress event will stop Ctrl+V paste keys but your users may like using Ctrl+V paste. How would you feel if Ctrl+V paste was removed from VS.NET? Adding handling for Ctrl+V paste will make our control a finished, production ready component.

Using the Control

The beauty of this control is that you never need to think about numeric data entry again. Simply add the control, set the InputType property and you're ready to go.

The IsValid() method is the heart of the NumEdit control. There are a few preliminary checks at the beginning of the method that handle the initial negation ("-") character, any leading "0" characters, and empty strings. The remainder of the method simply attempts to parse the string into the selected data type and returns false if any exceptions are thrown. If the IsValid() method returns false, the KeyPress event removes the current keystroke.

C#
private bool IsValid(string val)
{
	// this method validates the ENTIRE string
	//	not each character
	// Rev 1: Added bool user param. This bypasses preliminary checks
	//	that allow -, this is used by the OnLeave event
	//	to prevent
	bool ret = true;

	if(val.Equals("")
		|| val.Equals(String.Empty))
		return ret;
	
	if(user)
	{
		// allow first char == '-'
		if(val.Equals("-"))
			return ret;
	}

//	if(Min < 0 && val.Equals("-"))
//		return ret;

	// parse into dataType, errors indicate invalid value
	// NOTE: parsing also validates data type min/max
	try
	{
		switch(m_inpType)
		{
			case NumEditType.Currency:
				decimal dec = decimal.Parse(val);
				int pos = val.IndexOf(".");
				if(pos != -1)// 2 decimals + "."
			           ret = val.Substring(pos).Length <= 3;
			    //ret &= Min <= (double)dec && (double)dec <= Max;
				break;
			case NumEditType.Single:
				float flt = float.Parse(val);
				//ret &= Min <= flt && flt <= Max;
				break;
			case NumEditType.Double:
				double dbl = double.Parse(val);
				//ret &= Min <= dbl && dbl <= Max;
				break;
			case NumEditType.Decimal:
				decimal dec2 = decimal.Parse(val);
				//ret &= Min <= (double)dec2 && (double)dec2 <= Max;
				break;
			case NumEditType.SmallInteger:
				short s = short.Parse(val);
				//ret &= Min <= s && s <= Max;
				break;
			case NumEditType.Integer:
				int i = int.Parse(val);
				//ret &= Min <= i && i <= Max;
				break;
			case NumEditType.LargeInteger:
				long l = long.Parse(val);
				//ret &= Min <= l && l <= Max;
				break;
			default:
				throw new ApplicationException();
		}
	}
	catch
	{
		ret = false;
	}
	return ret;
}

Points of Interest

After adding the Ctrl+V pasting code I discovered a default ContextMenu for the base class TextBox that includes a Paste command. This command bypassed all my carefully crafted code and allowed non-numeric values into the NumEdit control. I was unable to find a way to intercept this Paste command. My solution was to simply replace the TextBox ContextMenu with an empty menu, thereby removing the ContextMenu. If anyone has any ideas about overriding this ContextMenu, I would appreciate hearing from you.

Enhancements

After completing the NumEdit control, I thought of a few possible enhancements.

  1. Min/Max property. This would allow restricting the minimum/maximum values inside the data type min/max values.
  2. Positive-/Negative-only property. This could be handled with the Min/Max property so it is redundant but may be easier to use.
  3. Scientific or Engineering notation such as 12.345E10 could be useful.

History

Release 2/17/2003

Rev 1 4/4/2003

  1. Fixed 0 value not allowed.
  2. Added OnLeave handler to avoid "-", "-0", or "000" entries
  3. Added handling for Shift+Insert pasting
  4. Added Min/Max Property IMPORTANT NOTE: This feature has been commented out in the Source Code. VS.NET crashes with no error messages when you attempt to open the visual designer for any form containing NumEdit controls with the Min/Max Property enabled. I have not determined the exact cause, but it appears to be related to the double datatype used by the Min/Max properties. Initial searches indicate a possible bug related to the double.MinValue, double.MaxValue static value handling. NOTE: Using Min/Max values could also be problematic. Take for example a Max value of 100. User enters 20, and the NumEdit control disallows any further entry since any additional digit would exceed 100. This behavior is likely to be confusing to the end user.

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


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionWhat License? Pin
Kunalpatel4-Jun-07 6:00
Kunalpatel4-Jun-07 6:00 
GeneralMin and Max Pin
Christopher Stratmann26-Mar-07 4:14
Christopher Stratmann26-Mar-07 4:14 
GeneralRe: Min and Max Pin
Oscar Bowyer26-Apr-07 16:10
Oscar Bowyer26-Apr-07 16:10 
Thanks Chris, I have one small finished app using this control where I have plans to add AllowNegative type functionality. Thanks for the suggestions and I will use these when I make to updates. Unfortunately I can't guarantee when that might happen, so feel free to have a go. Let me know how it turns out! Smile | :)

Oscar
GeneralBinding support Pin
Chals21-Jun-06 5:44
Chals21-Jun-06 5:44 
Generalre: Adding Date and Time Pin
ljscottiii8-Dec-05 6:40
ljscottiii8-Dec-05 6:40 
GeneralDisabling the Context Menu Pin
ro_xxx3-Nov-05 20:28
ro_xxx3-Nov-05 20:28 
Questionany updates? Pin
DaTom2-Sep-04 1:30
DaTom2-Sep-04 1:30 
Generaltrouble with . or , in floats Pin
kenneth nielsen5-Apr-04 7:01
kenneth nielsen5-Apr-04 7:01 
GeneralPasting bug Pin
krugs52525-Mar-04 9:19
krugs52525-Mar-04 9:19 
GeneralFound another bug: too many '.' Pin
Gabriel Nica28-Feb-04 11:01
Gabriel Nica28-Feb-04 11:01 
GeneralRe: Found another bug: too many '.' Pin
Oscar Bowyer29-Feb-04 14:16
Oscar Bowyer29-Feb-04 14:16 
Generalfound a bug Pin
JVMFX29-Aug-03 3:34
JVMFX29-Aug-03 3:34 
GeneralRe: found a bug Pin
Oscar Bowyer29-Aug-03 16:35
Oscar Bowyer29-Aug-03 16:35 
QuestionA few other enhancements? Pin
Paul Auger24-Mar-03 11:53
Paul Auger24-Mar-03 11:53 
GeneralUsers can use "Shift + Insert" to input invalid data Pin
DuNguyen10-Mar-03 1:55
DuNguyen10-Mar-03 1:55 
GeneralRe: Users can use "Shift + Insert" to input invalid data Pin
Paul Auger24-Mar-03 10:50
Paul Auger24-Mar-03 10:50 
GeneralNumEditType.Currency is limited to '.' Pin
KarlTschuemperlin1-Mar-03 10:02
KarlTschuemperlin1-Mar-03 10:02 
GeneralOne small issue: can't just put a '0' Pin
Anonymous27-Feb-03 15:15
Anonymous27-Feb-03 15:15 
GeneralRe: One small issue: can't just put a '0' Pin
Oscar Bowyer27-Feb-03 16:56
Oscar Bowyer27-Feb-03 16:56 
GeneralHandle Paste Pin
David M. Kean26-Feb-03 10:49
David M. Kean26-Feb-03 10:49 
GeneralRe: Handle Paste Pin
Oscar Bowyer26-Feb-03 12:28
Oscar Bowyer26-Feb-03 12:28 
GeneralRe: Handle Paste Pin
random.placeholder26-Feb-03 22:40
random.placeholder26-Feb-03 22:40 
GeneralRe: Handle Paste Pin
David M. Kean27-Feb-03 9:12
David M. Kean27-Feb-03 9:12 
GeneralRe: Handle Paste Pin
Merlin900013-Jun-03 10:11
Merlin900013-Jun-03 10:11 
GeneralAnother Method to consider Pin
Michael Potter26-Feb-03 9:53
Michael Potter26-Feb-03 9:53 

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.