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.