Sasha Sydoruk

Building a better mousetrap with XHTML, AJAX and RSS

HowTo – CompositeControl with a TextBox and a bunch of Validators

Here is an example of how I create composite controls in small server control library. It is pretty handy. With controls like this you can say something like this:

<csc:textbox id=”customServerControl1″ minlength=”4″ maxlength=”10″ required=”true” runat=”server” />

And that’s it! The composite control will automatically add the required validators and will create appropriate error messages!

Here is the source code:

using System;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace SashaSydoruk.Web.UI.WebControls
{
[AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
[ToolboxData("< {0}:textbox required=\"false\" runat=\"server\" />")]
[ValidationProperty("Text")]
public class TextBox : CompositeControl
{
protected System.Web.UI.WebControls.TextBox _textBox = null;
protected RequiredFieldValidator _reqValidator = null;
protected RegularExpressionValidator _regExValidator = null;
protected TextBoxLengthValidator _lengthValidator = null;
protected string _regExValidatorErrorMessage = string.Empty;

#region Constructors

public TextBox()
{
EnsureChildControls();
}

#endregion

#region Error Messages

public const string REQUIRED = "is a required field.";
public const string REGEX = "is invalid.";
public const string LENGTH = "length has to be {0} to {1} characters long";

#endregion

#region Public Properties

public System.Web.UI.WebControls.TextBox InnerTextBox
{
get { return _textBox; }
}

public RequiredFieldValidator InnerRequiredFieldValidator
{
get { return _reqValidator; }
}

public RegularExpressionValidator
InnerRegularExpressionValidator
{
get { return _regExValidator; }
}

public TextBoxLengthValidator InnerTextBoxLengthValidator
{
get { return _lengthValidator; }
}

public TextBoxMode TextMode
{
get { return _textBox.TextMode; }
set { _textBox.TextMode = value; }
}

public bool ReadOnly
{
get
{
object o = ViewState["ReadOnly"];
if(o == null)
{
return false;
}
else
{
return bool.Parse(o.ToString());
}
}
set { ViewState["ReadOnly"] = value; }
}

public int MaxLength
{
get { return _lengthValidator.MaximumLength; }
set
{
_lengthValidator.MaximumLength = value;
SetupValidators();
}
}

public int MinLength
{
get { return _lengthValidator.MinimumLength; }
set
{
_lengthValidator.MinimumLength = value;
SetupValidators();
}
}

public string RegularExpression
{
get { return _regExValidator.ValidationExpression; }
set
{
_regExValidator.ValidationExpression = value;
SetupValidators();
}
}

public string DisplayName
{
get
{
object o = ViewState["DisplayName"];
if(o == null)
{
return string.Empty;
}
else
{
return o.ToString();
}
}
set
{
ViewState["DisplayName"] = value;
SetupValidators();
}
}

public bool Required
{
get { return _reqValidator.Visible; }
set
{
_reqValidator.Visible = value;
SetupValidators();
}
}

public virtual string Text
{
get { return _textBox.Text; }
set { _textBox.Text = value; }
}

#endregion

protected override void OnInit(EventArgs e)
{
EnsureChildControls();
base.OnInit(e);
}

protected override void Render(HtmlTextWriter writer)
{
_textBox.Width = Width;
_textBox.Height = Height;
_textBox.RenderControl(writer);

_reqValidator.RenderControl(writer);
_lengthValidator.RenderControl(writer);
_regExValidator.RenderControl(writer);
}

protected override void CreateChildControls()
{
Controls.Clear();

_textBox = new System.Web.UI.WebControls.TextBox();
_textBox.ID = "textBox";
Controls.Add(_textBox);

//Add required validator
_reqValidator = new RequiredFieldValidator();
Controls.Add(_reqValidator);

//Add length validator
_lengthValidator = new TextBoxLengthValidator();
Controls.Add(_lengthValidator);

//Add RegularExpression validator
_regExValidator = new RegularExpressionValidator();
Controls.Add(_regExValidator);

if(Width.Value == 0)
{
_textBox.Width = Unit.Pixel(170);
}

Required = false;

SetupValidators();
}

private void SetupValidators()
{
_reqValidator.Display = ValidatorDisplay.None;
_reqValidator.ControlToValidate = _textBox.ID;

_lengthValidator.Display = ValidatorDisplay.None;
_lengthValidator.ControlToValidate = _textBox.ID;

_regExValidator.Display = ValidatorDisplay.None;
_regExValidator.ControlToValidate = _textBox.ID;

if(MaxLength > 0)
{
_textBox.MaxLength = MaxLength;
}

_lengthValidator.Visible = (MaxLength > 0 || MinLength > 0);

_regExValidator.Visible = RegularExpression.Length > 0;

_reqValidator.ErrorMessage = DisplayName + " " + REQUIRED;

if(MinLength == 0 && MaxLength > 0)
{
_lengthValidator.ErrorMessage = DisplayName + " "
+ string.Format("is too long. {0} characters max.", MaxLength);
}
else if(MinLength > 0 && MaxLength == 0)
{
_lengthValidator.ErrorMessage = DisplayName + " "
+ string.Format("is too short. {0} characters min.", MinLength);
}
else if(MinLength > 0 && MaxLength > 0)
{
_lengthValidator.ErrorMessage = DisplayName + " "
+ string.Format("has to be {0} to {1} characters long.", MinLength, MaxLength);
}
else if(MinLength > 0 && MaxLength > 0 && MinLength == MaxLength)
{
_lengthValidator.ErrorMessage = DisplayName + " " + string.Format("has to be {0} characters long.", MinLength);
}

_regExValidator.ErrorMessage = DisplayName + " " + REGEX;
}
}
}
2 comments

2 Comments so far

  1. Dominick January 25th, 2007 6:49 am

    There does not seem to be a “TextBoxLengthValidator” built into .net for this composite control to work. Also, this line in your post “With controls like this you can say something like this:” is not followed by an example.

    Anyway, thanks for the post!

  2. osydoruk January 25th, 2007 10:13 am

    Hi Dominick,

    Yes you are absolutely right, there is no TextBoxLengthValidator in .net framework. That is a custom Validator that I have built to validate minimum and maximum length of text. I will publish the source of the control some time in the future.

    I also fixed the example. It seems like WordPress is swallowing asp.net examples, so I had to manually HTML encode it.

Leave a reply