ASP.NET MaskedTextBox Custom Control

A lightweight, fast MaskedTextBox that validates input as Integer Only, Alpha Only, Email address, Web Address, SSN, US Zip Code, Date in MM-DD-YYY format, and Date in YYY-MM-DD format, as well as US 10-digit phone numbers.

I looked around for a decent ASP.NET Masked TextBox control and I found a couple of open source offerings. One of them that I liked was a halfway decent approach, but it had some major flaws. The REGEX for Alpha - only was wrong, and it had no designer so if you dragged one onto a page from the ToolBox you would never see anything there. In addition it had no Text property so there was no simple way to get the value the user had entered correctly in the control on a postback!

So after saying "DOH" a couple of times,  I spent some time adding a simple Designer (which allows resizing) and fixed up and tested all the Regex, and I added a Text property. I also added a US 10-digit phone number option.   I'm presenting it here in finished form. It's in Visual Studio 2008 so for those still using that, you are good to go.

The control handles Integer Only, Alpha Only, Email address, Web Address, SSN, US Zip Code, Date in MM-DD-YYY format, and Date in YYY-MM-DD format, as  well as US 10-digit phone numbers.

It doesn't actually create a "mask" inside the textbox like " /  /  " for a date, so you need to show a format example next to the control for the user. But it works very well and requires no external javascript, as it internally generates it's own validation controls. The control is very lightweight and  weighs in at just 20k.

Among other features, the control allows you to set your "Required" error message as well as a validation error message. Instead of running around hooking up validation logic, here's a single control for some of the most common cases.

It's flexible because you can use other external validation controls with it. For example, you might have a CustomValidator that sets the Required property of the MaskedTextBox to false based on the state of some radio button.

NOTE: While working on this control in Visual Studio 2008, I kept getting "Error creating control- [text] property" when ever I modified the code. It turns out this was a bug in VS2008 and there is a hotfix for it if you ever run into this.

Here's the "fixed up" new and improved, etc. code:

using System;
using System.Text;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Web.UI;
using System.Web.UI.Design;
using System.Web.UI.Design.WebControls;
using System.Web.UI.WebControls;
using System.IO;
using System.Text;

namespace PAB.WebControls
{

public enum DataTypeEnum { IntegerOnly =0 ,
StringOnly =1,
EmailAddress =2,
WebAddress =3,
SSNNumber =4,
USZipCode =5,
DateMMDDYYY =6,
DateYYYMMDD=7 ,
                                US10DigitPhone = 8
    } ;

[ToolboxBitmap(typeof(System.Web.UI.WebControls.TextBox)) ,
ToolboxData("<{0}:MaskedTextBox runat=\"server\" Required=\"true\" DataType=\"IntegerOnly\" > </{0}:MaskedTextBox>"),
     DesignerAttribute(typeof(MaskedTextBoxDesigner))
]

public class MaskedTextBox  : System.Web.UI.WebControls.WebControl ,INamingContainer

{
#region Private Members
private RegularExpressionValidator  _emailFormatValidator;
private RequiredFieldValidator _emailRequiredValidator;
private TextBox _emailTextBox;
private DataTypeEnum _DataType ;
private string _ErrorMessage=  string.Empty;
    private string _RequiredErrorMessage = string.Empty;
private bool   _Required =false;
private ValidatorDisplay _Display  = ValidatorDisplay.Dynamic;

string[] arrRegEx = {
"^([-]|[0-9])[0-9]*$", //integer Only
"^[a-zA-Z][a-zA-Z\\s]+$", //alphabet  Only
@"[\w-]+(?:\.[\w-]+)*@(?:[\w-]+\.)+[a-zA-Z]{2,7}", //Email address
@"http://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?",      //Internet Address Only
@"\d{3}-\d{2}-\d{4}", //SSN No
@"\d{5}(-\d{4})?",    //US Zip Code
@"(0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.](19|20)\d\d", //Date in MM-DD-YYY format
@"(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])"  , //Date in YYY-MM-DD format
                                 @"^[01]?[- .]?(\([2-9]\d{2}\)|[2-9]\d{2})[- .]?\d{3}[- .]?\d{4}$" // US 10 digit phone
};
#endregion

#region Properties
[Category("Data"),
DefaultValue(1 ),
Description ("Text box DataType") ]
            public PAB.WebControls.DataTypeEnum DataType
{
get { return _DataType ;}
set { _DataType = value;}
}

[Category("Data"),
DefaultValue(1),
Description ("Display Mode") ]
public  ValidatorDisplay Display
{
get {  return _Display ;}
set { _Display = value;}
}


[Category("Data"),
DefaultValue(1),
Description ("Text box DataType") ]
public  bool Required
{
get { return _Required ;}
set { _Required = value;}
}

[Category("Data"),
DefaultValue(1),
Description ("Error Message format") ]
public  string ErrorMessage
{
get { return _ErrorMessage  ;}
set { _ErrorMessage  = value;}
}

[Category("Data"),
DefaultValue(1),
Description ("Error Message for Required Validation") ]
public  string RequiredErrorMessage
{
get { return _RequiredErrorMessage  ;}
set { _RequiredErrorMessage  = value;}
}

             [Category("Display"),  
             DefaultValue(""),
             Description("Text Value of Control")]
            public string Text
             {
                 get
                 {
                      try
                     {
                          return this._emailTextBox.Text;
                     }
                      catch
                      {
                          return "";
                     }
                 }
                 set
                 {
                      try
                     {
                          this._emailTextBox.Text = value;
                    }
                    catch
                    {
                    }
                }
            }


#endregion

#region Constructor
public MaskedTextBox()
{

}
#endregion

protected override void OnInit(EventArgs e)
{

base.OnInit (e);
}

protected override void CreateChildControls()
{

Controls.Clear();
_emailTextBox = new TextBox();
_emailTextBox.ID = "emailTextBox";
_emailRequiredValidator = new RequiredFieldValidator();
_emailRequiredValidator.ID = "emailRequiredValidator";
_emailRequiredValidator.ControlToValidate = _emailTextBox.UniqueID;
_emailRequiredValidator.ErrorMessage = _RequiredErrorMessage;
_emailRequiredValidator.Display = _Display;

_emailFormatValidator = new RegularExpressionValidator();
_emailFormatValidator.ID = "emailFormatValidator";
_emailFormatValidator.ControlToValidate = _emailTextBox.ID;
int iValidExp =  _DataType.GetHashCode();
_emailFormatValidator.ValidationExpression = arrRegEx[iValidExp];
_emailFormatValidator.ErrorMessage = _ErrorMessage;
    _emailFormatValidator.Display = _Display;
this.Controls.Add(_emailTextBox);
if(_Required)
{
this.Controls.Add(_emailRequiredValidator);
}
this.Controls.Add(_emailFormatValidator);

}

#region Render Method
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
base.Render (writer);
}
#endregion

}
     public class MaskedTextBoxDesigner : ControlDesigner
     {
         public override string GetDesignTimeHtml()
         {
              StringWriter writer = new StringWriter();
             HtmlTextWriter html = new HtmlTextWriter(writer);
             MaskedTextBox control = this.Component as MaskedTextBox;            
             Initialize(control);
             if (control.Width ==  Unit.Empty )
                 control.Width = 100;
             if (control.Height == Unit.Empty)
                 control.Height = 18;
             control.RenderControl(html);
             return writer.ToString();          
         }

          
         public override bool AllowResize
         {
             get
             {
                 return true;
             }
         }

     }
}

NOTE: 10/21/2010 - Updated code so the Width property correctly sizes control.
You can download a Visual Studio 2008 Solution with Test Web here.

By Peter Bromberg   Popularity  (5911 Views)