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

C# MaskedEdit Control

Rate me:
Please Sign up or sign in to vote.
3.84/5 (26 votes)
26 Apr 2003CPOL7 min read 249.2K   2.1K   57   45
C# MaskedEdit Control similiar to the MS Access masked edit control

Sample Image - MaskedEdit.gif

Introduction

Visual Studio.NET and the .NET Framework includes many very useful controls. Unfortunately a MaskedEdit control was not among them. Anyone who has used the VS 6.0 MaskedEdit control knows that Microsoft's last attempt was not without its problems. MS Access developers have always had a useable MaskedEdit control. I wonder sometimes why Microsoft hasn't adapted the Access control to their other tools. Anyway I decided to tackle this very useful but missing control.

After spending a few hours working to handle character selection in the TextBox based control, I began to understand why someone might avoid building this control. Then came setting the MaskedEdit control value which introduced a new set of challenges. The difficulty of building a bullet proof MaskedEdit became apparent very rapidly - so this is fair warning, don't forget to test, test, test.

Background

The MaskedEdit control is loosely based on the Access mask behavior and includes the following features:

  • Standard InputMasks
    • Social Security Number (SSN)
    • Phone Numbers
    • Zip Codes
  • Custom InputMasks
  • Runtime changable InputMask
  • IsValid Property
  • Text Property (includes literals)
  • Value Property (excludes literals)
  • Input Char Property (defaults to '_')

Using the MaskedEdit Control

The following characters have been defined as mask characters for the MaskedEdit control

0 - digit required
9 - digit optional
L - lower case letter (a-z) required
l - lower case letter optional
U - upper case letter (A-Z) required
u - upper case letter optional
A - any case letter required
a - any case letter optional
D - letter or digit required
d - letter or digit optional
C - any char including punctuation

If you are not familiar with mask characters, you can find information in the MSDN library under "InputMask Property"

Regular expressions are used to define each mask char above. So for example '0' and '9' mask characters are coded as:

m_regexps.Add('0', @"[0-9]");        // digit required
m_regexps.Add('9', @"[0-9 ]");        // digit/space not required

You can find all the other mask character RegExp's in the source code for the MaskedEdit control. The space ' ' character is used as the optional character. Validation code in other parts of the MaskedEdit control use the space character to determine if an entry is required. This is a key consideration if you decide to define your own input mask characters.

The input mask chars that I've defined are basically groups of digits, upper and lower case letters along with ANY mask character 'C'. I think these should be suitable for many circumstances but if you have a need for more finely tuned input restrictions, the MaskedEdit control can handle it. For example, suppose you have a need to input hexadecimal values. None of the current input mask chars handle hex digits (0 through 9 plus A through F). So lets add a new mask char for hex digits, which would look like

m_regexps.Add('H', @"[0-9A-F]");        // hex digit required

This regexp would permit any of these characters "0123456789ABCDEF". So an InputMask for a 16 bit hex value might look like "\0xHHHH" would be displayed as 0x____ with 4 positions for hex digit entry. This means that you can adapt the MaskedEdit control to handle new input requirements. Don't forget that if you add an input mask char '-', that the standard InputMasks will be adversely affected.

If you're paying close attention you may have a question about the InputMask above. What is the '\' char? If you need to add a literal char that is already defined as a mask char then you will need to use the escape char '\'. This causes the MaskedEdit control to consider the next InputMask character a literal instead of an input mask character. For example, let suppose we want an InputMask to allow the user to input part numbers in the form

UL-1234

where UL- are literals and 1234 represent required digits. Both 'U' and 'L' are input mask characters for Upper and Lower case characters. Adding literal 'U' or 'L' means that we must add the escape character to designate them as literals instead of input mask characters, so our InputMask would be

\U\L-0000

Note that the '-' does not need the escape char prefix since it is not defined as a mask char.

MaskedEdit Properties

Next lets look at how to get and set the value contained in the MaskedEdit control.

Text Property - This property sets/gets the entire string contained in the control including literals. So an SSN input mask with data filled in such as

123-45-6789

will return "123-45-6789".

Value Property - This property sets/gets ONLY the input chars from the control excluding literals. So the example above would return "123456789". The value prop does NOT return optional chars that have not been entered by the user so for example:

(___) 123-4567

entered into a phone number mask would return "1234567" from the Value prop. Optional input mask chars cause some interesting problems that I have worked to handle. I would recommend using the MaskedEditTest application to test any InputMask you plan to use to make sure it works as you would expect.

The remainder of the MaskedEdit properties are pretty sraight forward.

  • IsValid Property - Returns true if all required input chars have been entered correctly.
  • InputChar Property - Defaulted to '_' underscore char but can be set to any other char except input mask chars or the escape char.
  • ErrorInvalid Property - Defaulted to false. Setting this to true will cause the MaskedEdit control to throw errors if attempts are made to set Text or Value props to an invalid string. Setting this to true during debugging could prove very useful.
  • StdInputMask Property - enum to select a standard input mask including
    • None - makes the MaskedEdit control work like a standard text box
    • SSN
    • Phone
    • Zip
    • Custom - use this to define custom input mask
  • InputMask Property - Use this to set custom InputMasks. The InputMask CAN be changed during runtime. The MaskedEdit control attempts to convert the current text into the new mask. This is LIKELY to cause problems. If you need to reset the mask during runtime, I would recommend setting the Value to an empty string prior to resetting the InputMask.

Usage Considerations

The MaskedEdit should work well for inputting "known" values such as SSN, phone and zip. The important point is that the user must KNOW what is to be entered since the mask doesn't give any clues as to the type of input expected (digits?, alpha chars?, ???). Tool tips or help files might be useful to explain complex input masks. Providing messages when invalid characters are entered by the user is a possible improvement. I am considering adding an InValid event, and an InValidMessage property to allow developers to add customized messages fired during invalid entry. Let me know your thoughts.

Setting the InputMask to only literal chars makes this a label control. I considered adding handling for this possibility but decided against it. If you try this, be prepared to catch errors :-\

Selection of characters in the MaskedEdit control is designed to keep the selection on input chars only and to skip over literals. This causes a somewhat peculiar selection behavior.

The base class TextBox has an extensive number of properties. I have added handling for some of these properties that I know affect the MaskedEdit control. There may be other props that I haven't considered that will cause problems or errors. Please post a note if you find one.

TODO

  1. Test, Test, Test I've spent more time than I would like to admit testing this control but as anything with this level of complexity, undiscovered bugs may exist. Please post a note if you find a bug.
  2. Add data binding features. I would anticipate binding the Text, Value, and InputMask properties. Let me know your thoughts on this.
  3. The MS Access has a feature to automatically upper/lower case input '<' = lower case, '>' = uppercase. This feature is not included in the MaskedEdit control. Let me know if you have a need for this feature, and I will work to add it on Rev. 2

History

  • Released Rev 1.0 4/2/2003

License

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


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

 
GeneralYour Zip is a trash! Pin
Member 69538419-Mar-04 21:22
Member 69538419-Mar-04 21:22 
GeneralHandling Copy/Cut/Paste/Delete/Undo... Pin
Paul Young11-Mar-04 0:10
Paul Young11-Mar-04 0:10 
GeneralTwo small corrections ... Pin
Sebastien Lorion2-Jan-04 21:31
Sebastien Lorion2-Jan-04 21:31 
GeneralGreat!! Pin
Luis Alonso Ramos30-Dec-03 10:06
Luis Alonso Ramos30-Dec-03 10:06 
GeneralRe: Great!! Pin
Oscar Bowyer30-Dec-03 14:00
Oscar Bowyer30-Dec-03 14:00 
GeneralBug when erasing value with backspace Pin
Sebastien Lorion28-Dec-03 23:10
Sebastien Lorion28-Dec-03 23:10 
GeneralRe: Bug when erasing value with backspace Pin
Josef Meile3-May-05 6:05
Josef Meile3-May-05 6:05 
GeneralQuick DataBinding solution Pin
Zombies with Coffee, LLC9-Sep-03 3:54
professionalZombies with Coffee, LLC9-Sep-03 3:54 
I renamed 'Text' to 'MaskedText' and renamed the property 'Value' to 'Text' and removed the Hidden attribute.

I was able to databind to the Text field without any problems!
Good luck!
GeneralGreat!!! Pin
eric feng21-Jul-03 12:37
eric feng21-Jul-03 12:37 
GeneralRe: Great!!! Pin
Oscar Bowyer21-Jul-03 14:56
Oscar Bowyer21-Jul-03 14:56 
GeneralRe: Great!!! Pin
eric feng22-Jul-03 10:16
eric feng22-Jul-03 10:16 
GeneralSuggestion for allowing empty values Pin
Bob Nicksic30-Jun-03 19:50
Bob Nicksic30-Jun-03 19:50 
GeneralRe: Suggestion for allowing empty values Pin
Oscar Bowyer21-Jul-03 14:41
Oscar Bowyer21-Jul-03 14:41 
GeneralSuggestion Pin
Oleksandr Kucherenko10-May-03 3:17
Oleksandr Kucherenko10-May-03 3:17 
GeneralRe: Suggestion Pin
Oleksandr Kucherenko10-May-03 3:23
Oleksandr Kucherenko10-May-03 3:23 
GeneralRe: Suggestion Pin
Oscar Bowyer12-May-03 15:40
Oscar Bowyer12-May-03 15:40 
GeneralClipboard Bug Pin
Oleksandr Kucherenko10-May-03 3:12
Oleksandr Kucherenko10-May-03 3:12 
GeneralRe: Clipboard Bug Pin
Oscar Bowyer12-May-03 15:25
Oscar Bowyer12-May-03 15:25 
GeneralYour To Do List Pin
BrentSeufert29-Apr-03 11:19
BrentSeufert29-Apr-03 11:19 
QuestionLicense? Pin
kkm00027-Apr-03 0:01
kkm00027-Apr-03 0:01 
AnswerRe: License? Pin
PhallGuy11-Sep-03 13:56
PhallGuy11-Sep-03 13:56 
AnswerRe: License? Pin
Taha Elsayed24-Sep-04 15:32
Taha Elsayed24-Sep-04 15:32 

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.