Click here to Skip to main content
Click here to Skip to main content

Validating Edit Controls

By , 22 Feb 2004
 

Contents

Introduction

Textbox controls are often used to enter dates, times, currency values or preformatted numeric data such as phone numbers. A control that allows its user to only enter a specific type of data is useful for several reasons:

  1. The user may do less typing if the control automatically fills in characters such as dashes or slashes.
  2. The user gets immediate feedback if he/she enters an invalid character.
  3. The entered data is much more likely to be valid when the user "submits" it.

The classes presented in this article provide these benefits for the most popular types of data that may be entered: dates, times, decimals, integers, currency amounts, formatted numerics and restricted alphanumerics.

Background

This is my first real project using C#/.NET, having come from C++/MFC and Java. I decided that a great way to learn was to take something I'm already familiar with and convert it to C#. This would allow me to learn the new technology as well as to make note of the differences. This article is the result of converting my Validating Edit Controls code, originally written in C++/MFC. The effort took around a month to complete and was a terrific learning experience. Enjoy!

Classes

There are two groups of classes, the behavior classes and the textbox classes, both of which are contained in the AMS.TextBox namespace. The behavior classes are designed to alter the standard behavior of textboxes so that the user can only enter a specific type of text into the control. For example, the DateBehavior only allows a date value to be entered into the textbox associated with it. The rest of the classes are simple TextBox-derived controls containing specific behaviors. For example, the DateTextBox control has the DateBehavior field inside of it and a property used to retrieve it.

Here's a listing of all the classes. If you need specific documentation on the available methods and properties, you may view the AMS.TextBox.chm help file, or just use the editor's Intellisense.

Class Name Description
Behavior

Base class for all behavior classes. It has some basic functionality.

AlphanumericBehavior

Prohibits input of one or more characters and restricts length.

NumericBehavior

Used to input a decimal number with a maximum number of digits before and/or after the decimal point.

IntegerBehavior

Only allows a whole number to be entered.

CurrencyBehavior

Inserts a monetary symbol in front of the value and a separator for the thousands.

DateBehavior

Allows input of a date in the mm/dd/yyyy or dd/mm/yyyy format, depending on the locale.

TimeBehavior

Allows input of a time with or without seconds and in 12 or 24 hour format, depending on the locale.

DateTimeBehavior Allows input of a date and time by combining the above two classes.
MaskedBehavior

Takes a mask containing '#' symbols, each one corresponding to a digit. Any characters between the #s are automatically inserted as the user types. It may be customized to accept additional symbols.

AlphanumericTextBox

Supports the Alphanumeric behavior.

NumericTextBox

Supports the Numeric behavior.

IntegerTextBox

Supports the Integer behavior.

CurrencyTextBox

Supports the Currency behavior.

DateTextBox

Supports the Date behavior.

TimeTextBox

Supports the Time behavior.

DateTimeTextBox

Supports the DateTime behavior.

MaskedTextBox

Supports the Masked behavior.

MultiMaskedBehavior

Takes a mask and adopts its behavior to any of the above classes.

Usage

I've built all these classes into a DLL so that the TextBox-derived classes may be used inside the Visual Studio .NET IDE as custom controls. Here are the steps required for adding them to your project and using them in your code:

  1. Open your own project inside Visual Studio .NET.
  2. Open the file containing the form you wish to add the control(s) to.
  3. Right click on the Toolbox and select "Customize Toolbox".
  4. Click on the .NET Components tab.
  5. Click the Browse button and select the AMS.TextBox.dll file.
  6. The 9 controls will be added to the Customize toolbox and will be check marked. Click on the Namespace column to sort by it, so you can see them more easily.
  7. If you wish, remove the checkmark from the ones you're not going to use.
  8. Click OK. The controls will then appear on the toolbox.
  9. Drag and drop them to your form and use them like regular TextBoxes.
  10. The behavior-related properties will appear under the Behavior category in the Properties toolbox of the form designer.

Points of Interest

While porting these classes from C++, I came upon several important differences in how things are done. I decided to make note of these differences for future reference and added them here for anyone who may work on a similar task. If you want to read on, I recommend you first become familiar with the C++ classes.

Names

In the .NET world, Edit boxes are called TextBoxes (and Text controls are called Labels). So I knew that to keep things as .NETish as possible I had to rename my classes. I replaced the "Edit" suffix with "TextBox" and I put everything into a namespace called AMS.TextBox to keep the names as simple as possible.

No Hungarian Notation

For years I've used my own variation of Hungarian notation in C++ code. I thought it was a great way to ease the pain of maintenance.

Then I started writing Java code and I had to conform to the standards set by my group: no Hungarian notation. So I stopped using it, at least for Java. And to my surprise after about a month, I wasn't missing it! It was actually liberating to write variables without the extra baggage of the type prefix. It also made the code easier to read. I came to the realization that in well written, modular code it's rarely necessary to make each variable's type evident within the name itself. It's just overkill and it makes the name larger and more cluttered.

So I gave it up for good in Java, while I kept it in my existing C++ code for the sake of consistency. I had even replaced the m_ prefix (for member variables) with the this. prefix.

Then came C# and this project. I knew that Microsoft's convention had been to drop Hungarian notation for .NET, so I happily continued on as I had with Java. But I faced a small problem. I wanted to make the code CLS compliant so that it could be used and extended by any .NET language. This caused a problem for protected variables with names like "separator" and then a corresponding property called "Separator". Since the names were the same except for the casing, the code was not CLS compliant (for case-insensitive languages). So I decided to switch from using this. for member variables back to the old m_ convention, which I had always liked.

And that's the notation I use in this project. No Hungarian notation except for the m_ for all member variables (fields).

No Multiple Inheritance

When I originally wrote my C++ classes, I made the decision to split the CEdit classes from their behaviors - I believe this follows the Bridge pattern. This strategy gave me the flexibility of being able to plug the behaviors into multiple CEdit-derived classes as needed, which worked great for the CAMSMultiMaskedEdit class. In addition, I used C++ multiple-inheritance feature to conveniently inherit the classes from CEdit and their respective behavior(s) simultaneously.

As we all know, .NET does not support multiple implementation inheritance, so I had to come up with an alternative. I initially decided to forgo the idea of the TextBox-derived classes having the methods and properties of their respective behaviors, which multiple inheritance so conveniently allowed me. Instead I added a read-only property to each class called Behavior which returns the Behavior-derived object currently associated with the TextBox object. So any behavior-specific action would be taken via this property.

This approach made life much easier for me, the library developer, but not for anyone using the library. Whereas in C++ you could do this:

CAMSDateTimeEdit dt ...
int day = dt.GetDay(); 

In C# now you would need to do this:

DateTimeTextBox dt ...
int day = dt.Behavior.Day;

I went with this design for some time until I came to the conclusion that it just wasn't right. It was a step backward, and all because I didn't want to spend extra time wrapping the Behavior's public members in the TextBox-derived classes. So I bit the bullet and did it; I went through each TextBox class and added its corresponding Behavior's public methods and properties as members of the class. This essentially turned the TextBox classes as wrappers of their Behavior classes. It was a lot of extra work (caused by the lack of MI), but I think it was worth it. Now the TextBox classes are similar to their C++ counterparts:

DateTimeTextBox dt ...
int day = dt.Day;

This is not only more intuitive but also makes the TextBox classes more friendly for the form designer.

Less Coupling

For the C++ classes, I decided to make the CAMSEdit::Behavior class work only with classes derived from CAMSEdit. This definitely made life easier, since the CAMSEdit class was mine and I could enhance it with whatever methods were needed by the Behavior classes (i.e. GetText, GetValidText, IsReadOnly). But the problem was that this created a tight coupling between the Behavior classes and CAMSEdit, which any new class would have to account for.

For C#, I changed the Behavior classes to be much more independent. Now they work with any classes derived from System.Windows.Forms.TextBoxBase. This gives them the flexibility to be associated with just about any TextBox class and not just the ones derived some class of mine.

Additionally, I made it very easy to associate Behavior classes to textboxes. You just instantiate the behavior class and pass the textbox object in the constructor. Here's an example:

MyTrustyTextBox textbox = new MyTrustyTextBox();

// Alter the textbox to only take Time values
TimeBehavior behavior = new TimeBehavior(textbox);

That's it! From that point on, the textbox behaves according to the rules of that behavior. This is in sharp contrast to C++ where not only did the class need to be derived from CAMSEdit, but you also needed to forward several message handlers to the associated Behavior, as explained next.

Events

If you look at the C++ code, you'll notice that the Behavior classes rely on their associated CAMSEdit object to forward the relevant messages to them (OnChar calls _OnChar, OnKeyDown calls _OnKeyDown, etc.). Well, thanks to delegates I didn't need to do that in C#. All I had to do was make the Behavior class add event handlers to the textbox object that would call methods in the Behavior class. And since these methods are declared virtual in the Behavior class, then all the derived classes needed to do was, override them to provide their own functionality. This is a more elegant approach that in C++ would have ended up looking more like a hack if I had decided to implement it.

In addition, while in C++ I handled the messages directly (i.e., OnChar for WM_CHAR, OnKeyDown for WM_KEYDOWN, etc.), .NET does not provide direct handlers for some of these messages. The only way to do it, as far as I could see, was to override WndProc inside the textbox classes themselves and trap the messages there inside a switch statement.

Instead, I decided to try the available event handlers to see if they could do the job. So I used the KeyPress event for WM_CHAR, KeyDown for WM_KEYDOWN, TextChanged for WM_SETTEXT and LostFocus for WM_KILLFOCUS. They worked just fine and allowed the Behavior classes do all the work, as described above.

Validations

The Behavior classes are all about validations - basically ensuring that the user enters the proper data into the textbox. Some validations are performed as the user types while others happen when the user leaves the control.

As you may know, the System.Windows.Forms.Control class contains properties and events designed to help the developer validate the control's value when control loses focus. I decided to take advantage of this built-in mechanism and move a lot of the functionality in the old OnKillFocus handlers to a Validating event hander I added to the Behavior class. This handler not only validates the data, but also gives error feedback to the user via a message beep, message box, or a small icon (ErrorProvider). It can even be configured to automatically set the control to a valid value if necessary.

This is all accomplished by modifying the Flags property and setting the corresponding ValidationFlag value(s). Here's an example of how to make a beeping sound and show an icon if the control's value is empty or not valid when the Validating event is triggered:

DateTimeTextBox dt ...
dt.ModifyFlags((int)ValidatingFlag.ShowIcon
    | (int)ValidatingFlag.Beep,  true);

Of course, this also requires that the textbox's CausesValidation property is set to true, which by default it is. As an alternative, you may invoke all this functionality yourself via the textbox's Validate method. It is called by the Validating event handler to set the Cancel property.

Properties

First of all, I just have to say that I love properties! They're a welcome addition to C# (and they should have been part of Java). When converting these classes, a lot of methods became excellent candidates for properties. So I happily went and converted all of them.

Then I took a second look and reconsidered what I had done. I found that while a lot of methods were undeniably property-material, others were a bit more questionable. The most prominent one was Behavior.GetValidText. This one initially appeared like another method worthy of becoming a property with a getter. However, I later decided that properties should be treated by the programmer as convenient ways of quickly reading attributes of an object. If you look at the code for most GetValidText implementations, there is quite a bit of processing going on in there, much more than the typical return someField; which you find in most property getters. In other words, the "valid text" is not really a property of the behavior. It needs to be deciphered every time the method is called. So leaving it as a method does not give the impression that it's readily available and quickly retrieved.

This was the criteria I used when deciding which methods to turn into properties. If the property's getter had a simple implementation and the property itself made sense for the class, then I converted it; otherwise I left it as a method.

Documentation

After I had finished porting the classes, I decided it would be nice to document the code. The C++ code already had comments on the top of every method, so that gave me a head start. However I decided to explore the XML Documentation tags to see what additional benefits I could gain.

My first impression is that they were very verbose. Most of them require an opening and closing tag, which if written on separate lines can make each section take at least 3 lines! For methods that take multiple parameters that would mean an extra 3 lines of comment per parameter. That's a lot of space taken up in comments!

The benefits were another story. You spend some time up-front putting up with all the verbosity, but the end result is nicely formatted online help. This would also mean that I wouldn't have to spend extra time documenting every method within this article, like I did for the C++ one. You just add the DLL and its XML file to your project - Visual Studio takes care of the IntelliSense for you automatically!

So I did it! I manually documented every method, property and field in the classes, even the private ones, right in the code. To cut down on the waste of space produced by the opening and closing tags, I decided to only put the opening tags on lines by themselves. Closing tags would simply go as part of the last line of the section. I also added a couple of spaces for indentation to the contents to make them easier to read. Here's an example:

/// <summary>
///     Initializes a new instance of the class by also setting its 
///     mask and corresponding Behavior class. </summary>
/// <param name="mask">
///     The mask string to use for determining the behavior. </param>
/// <seealso cref="Mask" />

There's a tool called NDoc that generates help files from source code, in a variety of formats. I used it to generate an MSDN-style help file, AMS.TextBox.chm, which I've included in the download. Enjoy!

Acknowledgments

I'd like to thank Gerd Klevesaat for helping me understand the complexities of dealing with controls having sub-properties. I wanted to give users of my textbox controls, the ability to directly manipulate the various properties of the Behavior property, right from the form designer. After many trials and tribulations, I decided not to implement such functionality since it doesn't work as it should, but it was fine since I ended up wrapping most of the behavior public methods and properties inside the textbox classes.

History

  • Version 1.0 - Sep 15, 2003
    • Initial release. :-)
  • Version 1.1 - Nov 7, 2003
    • Fixed a problem related to the form designer, which was generating code for properties that I had marked with the Browsable(false) attribute, such as Day, Month and Year. The designer would set these to 0 and at run time they would raise exceptions since 0 isn't a valid value. To prevent this problem, I used the ControlDesigner class to manually remove those properties at design time. Thanks to Spiros Prantalos for reporting this problem.
    • Fixed a bug in the NumericBehavior class reported by Wojtek Swieboda (see below).
    • Added a description for the AMS.TextBox namespace to the help file (AMS.TextBox.chm).
  • Version 1.2 - Nov 26, 2003
    • Added a couple of NumericBehavior.LostFocusFlag values to allow the LostFocus handler to be called when the Text property is set or the text changes.
    • Added the new CallHandlerWhenTextPropertyIsSet flag to CurrencyBehavior so that when the Text property is set, the value is automatically appended with ".00" (if necessary). Thanks to Yan Khai Ng for bringing it to my attention.
  • Version 1.3 - Jan 9, 2004
    • Changed the Month, Day, Hour, Minute, and Second getters to be less strict about the expected format. This allows the Text property of the Date, Time, and DateTime controls to be properly bound to database columns. Thanks to Terry Carroll for reporting the problem.
    • Fixed a bug in the Alphanumeric behavior that wasn't removing invalid characters as expected.
  • Version 2.0 - Jan 30, 2004
    • Added extra event handlers to intercept when objects are added to the DataBindings collection of the control. This fixes problems with Date, Time, DateTime, and Numeric controls bound to nullable database columns. It also fixes problems with the Currency textbox which was not being properly converted to a Decimal when bound. Thanks to Terry Carroll, ACanadian, and MattH for reporting the problem.
    • Added a check to the ReadOnly property to prevent the Up/Down arrows from changing the Date or Time controls when read-only. Thanks to Terry Carroll for reporting this problem.
    • Changed the default range of values for the Integer textbox to the min and max 32-bit values to prevent a crash in the VS IDE. Thanks to mdenzin for reporting the problem and suggesting this fix.
    • Fixed a bug that was causing validations to fail when the control was empty. Thanks to marcelloz for helping me notice the bug.
    • Added a static ErrorCaption property to the Behavior class to be used in error message boxes for failed validations. Thanks to marcelloz for giving me the idea.

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

About the Author

Alvaro Mendez
Web Developer
United States United States
Member
I've done extensive work with C++, MFC, COM, and ATL on the Windows side. On the Web side, I've worked with VB, ASP, JavaScript, and COM+. I've also been involved with server-side Java, which includes JSP, Servlets, and EJB, and more recently with ASP.NET/C#.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 4memberFlash2009-MX29 Nov '12 - 8:47 
la estuve buscando
Suggestion想找中文翻译请看http://www.wisestudy.cn/article/english_opentech_vc6_Validating-Edit-Controls.htmlmembercpluspluswiser2 Apr '12 - 16:23 
该网站还有其它翻译
GeneralGood One!memberSushant Joshi7 Sep '10 - 2:18 
Good One!
Sucess is going from failure to failure without loss of enthusiasm.

GeneralMy vote of 3memberscandstone25 Jun '10 - 22:09 
simple but useful codeing
QuestionOn the place to put of a prefix, put a suffixmemberGerber Samuel23 Mar '10 - 22:33 
Is there a simply way to change the PREFIX into a SUFFIX in a case of NumericTextBox? I would like to do the same thing by using the poucentage!
like +-100%
 
But anyway thanks again Smile | :)
Samuel Gerber
QuestionBug Fix?membersnowman718613 Jan '10 - 8:37 
First, sorry for my bad english Smile | :)
 
I had problem using the NumericTextBox placed on a TabPage of a TabControl. Flags was set to display only an error message.
 
After I entered invalid data in my NumericTextBox, switching to a different tab made the error message popping 3 times to finally switch tab instead of giving focus to the guilty textbox.
 
To fix the problem, I just changed the call of MessageBox.Show() in Behavior.cs
public virtual void ShowErrorMessageBox(string message)
{
    MessageBox.Show(m_textBox, message, ErrorCaption, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
by this one,
public virtual void ShowErrorMessageBox(string message)
{
    MessageBox.Show(message, ErrorCaption, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
 
I don't really know what was the purpose of passing "m_textBox" as a parameter. Maybe someone can explain it?
 
By the way, excellent work!
 
Best regards,
Dave
GeneralDecimal errormemberStephcml3 Dec '09 - 5:01 
For a textbox with decimal, I have found and error.
 
If ever the decimal is changed to the OS, (Control Panel/Regional and Language Options), if the Regional Options /Customize/Decimal Symbol field is put to another symbol other than a dot ( . ), it will always pop up a message indicating that the value entered is invalid if ever a decimal is needed.
 
So I have changed the GetNumericText function in order to change the decimal not by a dot but by the real decimal from the OS.
 
		protected string GetNumericText(string text, bool realNumeric)
		{
			StringBuilder numericText = new StringBuilder();
			bool isNegative = false;
			bool hasDecimalPoint = false;
 
			foreach (char c in text)
			{
				if (Char.IsDigit(c))
					numericText.Append(c);
				else if (c == m_negativeSign)
					isNegative = true;
				else if (c == m_decimalPoint && !hasDecimalPoint)
				{
					hasDecimalPoint = true;
					numericText.Append(realNumeric ? NumberFormatInfo.CurrentInfo.NumberDecimalSeparator : m_decimalPoint.ToString());
				}
			}
		
			// Add the negative sign to the front of the number.
			if (isNegative)
				numericText.Insert(0, realNumeric ? '-' : m_negativeSign);
 
			return numericText.ToString();
		}
 

Yes the OS permits several character for the decimal but in fact I can't figure why. This code does not fully support it since the decimal is a char in the class.
 
But the class is pretty good.
GeneralNumericTextBox Fixmemberwahida21610 Jun '09 - 7:19 
Thx for this project, it's very interesting.
 
But i have found a bug !
When i tape 0,00 it's automatically changed to ,00 what is false Unsure | :~
So i've changed the code in the HandleLostFocus in NumericTextBox to :
 
bool isNegative = (text[0] == m_negativeSign);
if (isNegative)
text = text.Substring(1);

// Don't delete the first zero if it's alone
if (text.IndexOf(".") != -1)
{
string valEntiere = text.Substring(0, text.IndexOf("."));
if (valEntiere.Length > 1)
text = text.TrimStart('0');
}
if (text == "" || text[0] == m_decimalPoint)
text = '0' + text;
if (isNegative)
text = m_negativeSign + text;
 
But anyway thxxxxxxx again Smile | :)
 
Best regards.
Wahida
GeneralMy vote of 2membererik20558 Mar '09 - 22:25 
Needs update badly. VS2008 gives many warnings
AnswerBug FixmemberBaltazar_qc28 Nov '08 - 12:48 
Hello,
I found a problem when selecting all the content of a currency textbox containing a number that is more than 999 (that has a group separator), and then pressing a number to replace the value of the entire text.
 
Example:
text contains: 1 000,00
I double click to select all the text: 1 000,00
I then press '1' on the keyboard.
 
The result is that the cursor is now placed at the left of the '1', so if I wanted to write '1234', it would look like '2 341' instead!
 
to solve this, locate the HandleKeyPress override in the NumericBehavior Class in Behavior.cs.
 
replace line 2344:
m_previousSeparatorCount = separatorCount;
 
with:
if (m_selection.Length == this.TextBox.Text.Length)
    m_previousSeparatorCount = 0;
else
    m_previousSeparatorCount = separatorCount;
 
I hope that it helps you!
bye, and thank you btw for that nice piece of coding! Shucks | :->
 
René Destrempes

GeneralRe: Bug Fixmemberfactorx2222 May '09 - 12:20 
Otro bug similar sucede cuando esta todo el texto seleccionado y se presiona el separador decimal. La misma solucion funciona para ese caso.
 
Aplicar la misma solucion en la linea 2289
 

The same problem when selecting all the content of a currency textbox and pressing decimal separator to replace the value of the entire text.
 
the same solution in the line 2289
QuestionTimeTextBoxmemberCristiano de Morais Lima1 Sep '08 - 7:38 
When add TimeTextBox on my project, I received the following error:
System.IndexOutOfRangeException
 
What is this?
AnswerRe: TimeTextBoxmembers.kleinschmidt15 Jan '09 - 4:38 
Hi,
 
first i'd like to thank the author for the great code. I'm not using it directly, but it gave me inspiration. So i'm glad to be able to give a little bit back. I found the following bug:
 
The overridden OnSetComponentDefaults method in the Designer class is deprecated since .NET 2.0 and has no effect on the default values anymore.
I have found no solution for this one. But since the default text values (like "textBox1") aren't suppressed anymore, there are issues in the Minute and Second properties in TimeBehavior:
 
Change the get part of the
Minute 
property from
get
{
	string text = m_textBox.Text;				
	int startPos = text.IndexOf(m_separator, m_hourStart) + 1;
 
	if (startPos > 0 && text.Length >= startPos + 2)
		return ToInt(text.Substring(startPos, 2));
	
	return -1;				
}			
 
to this:
 
get
{
    string text = m_textBox.Text;
    if (m_hourStart < text.Length)
    {
        int startPos = text.IndexOf(m_separator, m_hourStart) + 1;
 
        if (startPos > 0 && text.Length >= startPos + 2)
            return ToInt(text.Substring(startPos, 2));
    }
    return -1;
}
 
and the get part of the
Second 
property from
 
get
{
	string text = m_textBox.Text;
	int startPos = text.IndexOf(m_separator, m_hourStart);
	if (startPos > 0)
	{
		startPos = text.IndexOf(m_separator, startPos + 1) + 1;
		if (startPos == 0)
			return -1;
	}
 
	if (text.Length >= startPos + 2 && Char.IsDigit(text[startPos]) && Char.IsDigit(text[startPos + 1]))
		return ToInt(text.Substring(startPos, 2));
 
	return -1;
}			
 
to this:
 
get
{
    string text = m_textBox.Text;
    if (m_hourStart < text.Length)
    {
        int startPos = text.IndexOf(m_separator, m_hourStart);
        if (startPos > 0)
        {
            startPos = text.IndexOf(m_separator, startPos + 1) + 1;
            if (startPos == 0)
                return -1;
 
            if (text.Length >= startPos + 2 && Char.IsDigit(text[startPos]) && Char.IsDigit(text[startPos + 1]))
                return ToInt(text.Substring(startPos, 2));
        }
    }
    return -1;
}
 
This should fix it. I hope this will help.
GeneralRe: TimeTextBoxmemberlonglybits10297 Dec '10 - 14:22 
thanks for your solution, I have got the same problem when with TimeTextBox, now I can work fine in VS2005.
GeneralCompile errormemberbvr6327 Jul '08 - 7:20 
I have an error in compile for "Use Unicode Character Set":
 
c:\vc\FrmAvi\FrmAvi\ValidatingEditSource\amsEdit.cpp(494) : error C2665: 'CAMSEdit::MaskedBehavior::Symbol::Symbol' : none of the 3 overloads can convert parameter 2 from type 'int (wint_t)'
c:\vc\FrmAvi\FrmAvi\ValidatingEditSource\amsEdit.h(211): could be 'CAMSEdit::MaskedBehavior::Symbol::Symbol(TCHAR,CAMSEdit::MaskedBehavior::Symbol::ValidationFunction,CAMSEdit::MaskedBehavior::Symbol::ConversionFunction)'
while trying to match the argument list '(char, overloaded-function)'
 
Help me, please
I use VS 2003.
GeneralRe: Compile error [modified]membermtwombley27 Sep '11 - 11:56 
In case anyone else runs into this, the problem is in the ValaidateionFunction typedef.
		
class AMSEDIT_EXPORT Symbol
{
  public:
    #ifndef _UNICODE
      typedef int (*ValidationFunction)(UINT);	// designed for functions such as _istdigit, _istalpha
      typedef UINT (*ConversionFunction)(UINT);	// designed for functions such as _totupper, _totlower
    #else
      typedef int (*ValidationFunction)(WCHAR);		
      typedef WCHAR (*ConversionFunction)(WCHAR);		
    #endif
...
should be
class AMSEDIT_EXPORT Symbol
{
  public:
    #ifndef _UNICODE
      typedef int (*ValidationFunction)(UINT);	// designed for functions such as _istdigit, _istalpha
      typedef UINT (*ConversionFunction)(UINT);	// designed for functions such as _totupper, _totlower
    #else
      typedef int (*ValidationFunction)(wint_t);		
      typedef WCHAR (*ConversionFunction)(WCHAR);		
    #endif
...


modified 23 Mar '12 - 13:04.

QuestionCan it be used in VC++/MFC (VS 6.0)memberrupanu12 Jun '08 - 20:24 
How do I use validations in VC++ edit boxes?
GeneralFix for if you get "Value cant be -1" bugmemberfc27 May '08 - 0:35 
If you use Numeric TextBox and set the DigitsInGroup to more than 0, you mite have noticed a random "Value cant be equal to -1 error" or sometimes it even says -2. Well here is the solution.
 
Just look for this funcion in the selection.cs file. And change it accordingly.
 
public void Set(int start, int end)
{
if (start < 0)
start = 0;
 
if (end < 0)
end = 0;
 
m_textBox.SelectionStart = start;
m_textBox.SelectionLength = end - start;
}
GeneralVisual Studio 2005memberMember 24630176 Apr '08 - 10:33 
I converted this to a Visual Studio 2005 project today without any real issues. Had to make a few trivial modifications to get rid of FXCop warnings that were coming up on build:
 
- in AMS.TextBox.TextBox.Designer, marked OnSetComponentDefaults with [Obsolete] attribute
- updated several XML cross-references to point to a specific overload of function (FXCop complained they were ambiguous). e.g. seealso cref="MoveBy" changed to seealso cref="MoveBy(int,int)"
- changed file headers that started with "/**" to "/*" to avoid interpreting as XML comment
 
Cheers,
 
-Richard
GeneralMinor addition to NumericTextBox for bindingmemberKen Teague30 Oct '07 - 8:57 
I noticed that there is an odd thing that happens during binding. If you try and bind to the actual output properties of the NumericTextBox - that is to say, if you bind to Double, Int, or Long - then the parsing behavior still assumes that the calling handler wants a string. To handle this, I changed HandleBindingParse in NumericBehavior.
 
protected override void HandleBindingParse(object sender, ConvertEventArgs e)
{
if (e.Value.ToString() == "")
e.Value = DBNull.Value;
else if (e.DesiredType == typeof(string))
e.Value = GetNumericText(e.Value.ToString(), false);
else if (e.DesiredType == typeof(Double))
e.Value = Double.Parse(GetNumericText(e.Value.ToString(), false));
else if (e.DesiredType == typeof(int))
e.Value = int.Parse(GetNumericText(e.Value.ToString(), false));
else if (e.DesiredType == typeof(long))
e.Value = long.Parse(GetNumericText(e.Value.ToString(), false));
}
GeneralDate Range Inputmemberdmenne14 Aug '07 - 21:36 
Thanks, Alvaro, for the great controls. It is one of the best allowing on-key validation.
 
Clearly, validation of dates is the most complex subject. I have found a bug which as far as I can see nobody has reported yet. The bug is hidden when the default settings of RangeMin/RangeMax are used.
 
Note: I am using Default DateBeforeMonth =true.
 
-- Set RangeMin to 1.1.2000 and RangeMax to 1.1.2005 (problem is hidden when you used 31.12.2005 for Range Max).
-- Try to enter 10.1.2001: You cannot
Typing the first 1 immediately changes it to 01.
 
This has to do with the missing year/month which is set to border-case min-max.
 
Dieter Menne
 

 

QuestionWhat License?memberKunalpatel4 Jun '07 - 5:59 
What license is the code released under? Is it the BSD? May I have a copy of the license? Thanks.
QuestionIs not beeping or showing any error messages anywheremembercorsairX10 May '07 - 4:29 
Hello,
 
first of all i would want to thank you for this wonderful work in doing such a control.
 

My question is related to the fact that even the textboxes are validating well, and not allowing to enter letters (the NumericTextBox and Integer), i couldn't succeed to make them show error on error provider or even beep.
 
I created a form, added 2 numerictextboxes, an errorprovider and then i go in the code of the constructor of the form and , after InitializeComponent() i add the line:
 
txtNumeric.ModifyFlags( ( int )ValidatingFlag.ShowIcon | ( int )ValidatingFlag.Beep , true );
 
Even i have no error (neither in designer, nor in the runtime), it is doing nothing.
 

Also another suggestion would be that, instead of working with flags (which are C++ original) to work with public properties. In fact i started to modify that, if you don't mind, to replace the Flags thing with more .NET closely public properties accessible from designer. (For example instead of coding the showerrormessages in flags, i will expose some public properties)
 

Thank you in advance for your reply.
Have a nice day

QuestionRangeMax and Numbers with commamemberHomerGER17 Apr '07 - 9:11 
hi
 
i set MaxRange to 100 and min to 0, MaxDecimalPlace is 1
Numeric1.ModifyFlags(Integer(ValidatingFlag.ShowIcon), True); (delphi.net)
 
if i use Integer is all OK but if i use Decimal i get a Error
for Example range is 0 to 100
ok is 30, 50 66 .....
 
but i get a Error for 23,5 or 34,1
 
sorry for my english
 


GeneralNumericTextBox [modified]memberaljay3 Apr '07 - 20:56 
Good day!
 
Having a problem when i change the numeric textbox property to right align but this control is very useful. Most of the users want numbers to be rightb aligned.
 
Also can currency textbox negative values enclosed in parenthesis instead of negative sign.
 
Thanks.
 

-- modified at 3:12 Wednesday 4th April, 2007

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

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130523.1 | Last Updated 23 Feb 2004
Article Copyright 2003 by Alvaro Mendez
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid