In my previous posts I walked thru the steps of adding a required validator and custom properties to a control. In this post I will show how to do the same to a list box control.
Step 1: Create a class extending the ListBox control and add private RequiredFieldValidator variable.
public class ListBoxReq : ListBox
{
#region Validator
/// <summary>
/// Validator
/// </summary>
private RequiredFieldValidator req;
#endregion
Step 2: Add properties you will want to set on the validator.
Notice
that the Validation Group property overrides the textbox property and
also sets the corresponding property on the validator if the validator
is not null. The Required property will be used to enable and disable
the validator. The rest of the properties will be used to set
properties on the validator control.
#region Properties
/// <summary>
/// ValidationGroup Property
/// </summary>
public virtual string ValidationGroup
{
get
{
string o = base.ValidationGroup;
return o;
}
set
{
String oldValue = ValidationGroup;
if (value != oldValue)
{
if (req != null)
{
req.ValidationGroup = value;
}
base.ValidationGroup = value;
}
}
}
/// <summary>
/// InvalidMessage Property
/// </summary>
[Browsable(true)]
[Description("InvalidMessage"), Category("Custom"), DefaultValue("")]
public virtual String InvalidMessage
{
get
{
object o = ViewState["InvalidMessage"];
if (o != null)
return (String)o;
return string.Empty; // Default value
}
set
{
String oldValue = InvalidMessage;
if (value != oldValue)
{
if (req != null)
{
req.ErrorMessage = value;
}
ViewState["InvalidMessage"] = value;
}
}
}
/// <summary>
/// Required Property
/// </summary>
[Browsable(true)]
[Description("Required"), Category("Custom"), DefaultValue(false)]
public virtual bool Required
{
get
{
object o = ViewState["Required"];
if (o != null)
return (bool)o;
return false; // Default value
}
set
{
bool oldValue = Required;
if (value != oldValue)
{
ViewState["Required"] = value;
}
}
}
/// <summary>
/// ClientScript Property
/// </summary>
[Browsable(true)]
[Description("ClientScript"), Category("Custom"), DefaultValue(true)]
public virtual bool ClientScript
{
get
{
object o = ViewState["ClientScript"];
if (o != null)
return (bool)o;
return true; // Default value
}
set
{
bool oldValue = ClientScript;
if (value != oldValue)
{
if (req != null)
{
req.EnableClientScript = value;
}
ViewState["ClientScript"] = value;
}
}
}
#endregion
Step 3: On Init
We will instantiate the RequiredFieldValidator
in the OnInit event, we also set the validator properties. You can see
the full life cycle of the page and controls and the order of the events
here. Since we don't want our code to execute at design time we check if we're in design mode at the top of our method. This code is almost the same as the previous example except we force the SelectionMode property to allow multiple selections.
#region On Init
/// <summary>
/// Init
/// </summary>
/// <param name="e"></param>
protected override void OnInit(EventArgs e)
{
//if we want this control to render at design time we need this code.
if (this.DesignMode)
{
base.OnInit(e);
return;
}
//default to multi select
this.SelectionMode = ListSelectionMode.Multiple;
//instantiate and setup the validator
req = new RequiredFieldValidator();
req.Enabled = false;
req.ControlToValidate = this.ID;
req.ErrorMessage = this.InvalidMessage;
req.Text = "Required";
req.EnableClientScript = ClientScript;
req.ValidationGroup = this.ValidationGroup;
req.Display = ValidatorDisplay.Dynamic;
Controls.Add(req);
}
#endregion
Step 4: Render
If the field is required we will render the textbox and the validator controls.
#region Render
/// <summary>
/// Render
/// </summary>
/// <param name="writer">Writer</param>
public override void RenderControl(HtmlTextWriter writer)
{
//if we want this control to render at design time we need this code.
if (this.DesignMode)
{
base.RenderControl(writer);
return;
}
//if required property is set to true enable the validator
if (Required == true)
{
base.Render(writer);
writer.Write("<span style=\"color:red;\">*</span>");
req.Enabled = true;
req.RenderControl(writer);
}
else
{
base.RenderControl(writer);
}
}
#endregion
Usage Example:
Markup
<%@ Page Title="" Language="C#" MasterPageFile="~/Site1.Master" AutoEventWireup="true" CodeBehind="ListBoxDemo.aspx.cs" Inherits="CustomControls.ListBoxDemo" %>
<%@ Register Assembly="CustomControls" Namespace="CustomControls.Controls" TagPrefix="cc1" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<cc1:ListBoxReq ID="ListBox" runat="server" Width="350px" Required="true">
<asp:ListItem Text="Option 1" Value="1"></asp:ListItem>
<asp:ListItem Text="Option 2" Value="2"></asp:ListItem>
<asp:ListItem Text="Option 3" Value="3"></asp:ListItem>
<asp:ListItem Text="Option 4" Value="4"></asp:ListItem>
</cc1:ListBoxReq>
<br />
<asp:CheckBox ID="ListBoxReqCheckBox" runat="server" Checked="true" Text="Required"
AutoPostBack="true" OnCheckedChanged="ListBoxReqCheckBox_CheckedChanged" />
<asp:button id="Submit" runat="server" causesvalidation="true" text="Submit" />
</asp:Content>
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace CustomControls
{
public partial class ListBoxDemo : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void ListBoxReqCheckBox_CheckedChanged(object sender, EventArgs e)
{
ListBox.Required = ListBoxReqCheckBox.Checked;
}
}
}
Examples:
Required Field:
Required Field after validation:
Complete Source:
Demo: