Create a custom control that inherits from the ASP text box control, and then add code to emit client-side script that limits the input to only numeric values.
Use the .NET language of your choice to:
Create a class that inherits from the Control
class in the System.Web.UI
namespace.
Override the OnPreRender
method to have it
generate the requisite client-side script.
Override the AddAttributesToRender
if you need to
add an attribute to the rendered control.
To use the custom control in an ASP.NET page:
Register the assembly containing the control.
Insert the tag for the custom control anywhere in the page.
Example 5-15 and Example 5-16 show the VB and C# class files for an example custom control that we have written to illustrate our approach. This custom control emits client-side script that checks key presses and allows only numeric keys to be entered into a text box. Example 5-17 shows how to use the custom control in an ASP.NET page.
Extending an existing ASP.NET server control is an easy way to create the functionality you need for an application. By inheriting your custom controls from existing controls, you are left to write only the code you need to add your special functionality.
To illustrate this approach, we’ve implemented a
text box control that allows only numeric input, a common project
requirement. Why is it necessary to implement a custom control to
accomplish this? First, it turns out that none of the ASP.NET
controls provides this functionality. And second, although you can
check the data entered in a text box to ensure it is numeric and
within a range with a range validator
, this does
not prevent the user from entering letters into the text box in the
first place. Extending the standard text box control by adding
client-side script that allows only numeric keys to be processed and
their values entered into the text box is a better solution.
The first step in extending the ASP.NET text box control is to create
a custom control class that inherits from
System.Web.UI.WebControls.TextBox
.
Next, you must override
the OnPreRender
method to generate the client-side script. (The reason for overriding
OnPreRender
is that you need to get the script
onto the page before the control is rendered.) This is done by
creating a string containing the script block, and then registering
it to be output to the page with the
Page.RegisterClientScriptBlock
method.
The client script must be created and output in an event that occurs
before the Render
event or the script will not be
output in the rendered page. This can be done in the
Load
or PreRender
events.
Be sure to call the base class OnPreRender
method.
Failure to do so can result in lost functionality if the base control
performs any operations in the OnPreRender
method.
It is important to output the client script using the
Page.RegisterClientScriptBlock
method with the
first parameter set to a constant value. This ensures that client
script is output to the page only once. If the client script was
output directly in the Render
event and the page
contained multiple instances of the custom control, the client script
would be output for each instance of the control.
The client-side script that is output to the page in our example is
shown next. It simply checks each key press to see if the
keycode
is in the 0-9 range and returns
true
if it is. Otherwise, it returns
false
.
<script language='javascript'> <!-- function checkKey( ) { var key = event.keyCode; var processKey = false; if ((key >= 0x30) && (key <= 0x39)) { processKey = true; } return(processKey); } //--> </script>
This script will work only for Internet Explorer. You can use the
Page.Request.Browser
object in the
OnPreRender
method to determine the browser type
and version so that you can output code specific to the browser
requesting the page.
The last step to implement our sample custom control is to add an
attribute to the rendered input control to cause the
checkKey
method to be executed when a key is
pressed with the focus set to the input control. This is done by
overriding the AddAttributesToRender
method and
adding the onkeypress
attribute.
If your application has a similar requirement to add an attribute to
the rendered input control, be sure to call the base class
AddAttributesToRender
method. Failure to do so can
result in lost functionality if the base control performs any
operations in the AddAttributesToRender
method.
The rendered HTML input control is shown here:
<input name="ccNumericInput" type="text" maxlength="10"
size="10" id="ccNumericInput" onkeypress="return checkKey( );"
/>
To complete the example, we insert the control into an ASP.NET page by first registering the control (see Example 5-17). We then place the control tag in the page just as if it were a plain-vanilla text box.
One of the great advantages of inheriting from an existing ASP.NET
server control is the support for all the control’s
inherent functionality. In this case, we can set any of the
attributes available for the asp:Textbox
control,
even though we did no coding for those properties in our control.
<ASPCookbook:CH05CustomControlNumericInputVB
id="ccNumericInput" runat="server"
Columns="10" MaxLength="10"
/>
JavaScript: The Definitive Guide, by David
Flanagan (O’Reilly), for more information on
browser-specific JavaScript; ASP.NET in a
Nutshell, by G. Andrew Duthie and Matthew MacDonald
(O’Reilly), and the MSDN Library for more on
OnPreRender
and
AddAttributestoRender
Example 5-15. Numeric input-only text box (.vb)
Option Explicit On Option Strict On '----------------------------------------------------------------------------- ' ' Module Name: CH05CustomControlNumericInputVB.vb ' ' Description: This class provides a custom control that implements an ' input control that only allows numbers to be input. ' '***************************************************************************** Imports System Imports System.Environment Imports System.Text Imports System.Web Imports System.Web.UI Namespace ASPNetCookbook.VBExamples Public Class CH05CustomControlNumericInputVB Inherits System.Web.UI.WebControls.TextBox 'the following constant defines the name of the name of the client-side 'JavaScript method used to process keystrokes Private Const CHECK_KEY_NAME As String = "checkKey" '************************************************************************* ' ' ROUTINE: OnPreRender ' ' DESCRIPTION: This routine handles the prerender event for the custom ' control. It adds clientside script to process keys ' before adding them to the textbox. '-------------------------------------------------------------------------Protected Overrides Sub OnPreRender(ByVal e As System.EventArgs)
Dim clientScript As StringBuilder
MyBase.OnPreRender(e)
'generate the opening script tag
clientScript = New StringBuilder
clientScript.Append("<script language='javascript'>" & NewLine)
clientScript.Append("<!--" & NewLine)
'generate code to check the key pressed
clientScript.Append("function " & CHECK_KEY_NAME & "( )" & NewLine)
clientScript.Append("{" & NewLine)
clientScript.Append("var key = event.keyCode;" & NewLine)
clientScript.Append("var processKey = false;" & NewLine)
clientScript.Append("if ((key >= 0x30) && (key <= 0x39))" & NewLine)
clientScript.Append("{" & NewLine)
clientScript.Append("processKey = true;" & NewLine)
clientScript.Append("}" & NewLine)
clientScript.Append("return(processKey);" & NewLine)
clientScript.Append("}" & NewLine)
'generate the closing script tag
clientScript.Append("//-->" & NewLine)
clientScript.Append("</script>" & NewLine)
'register script to be output when the page is rendered
Page.RegisterClientScriptBlock(CHECK_KEY_NAME, _
clientScript.ToString( ))
End Sub 'OnPreRender
'************************************************************************* ' ' ROUTINE: AddAttributesToRender ' ' DESCRIPTION: This routine handles the AddAttributeToRender event ' for the custom control. It adds the onkeypress ' attribute to the textbox to cause processing of all keys ' pressed when the textbox has focus. '-------------------------------------------------------------------------Protected Overrides Sub AddAttributesToRender( _
ByVal writer As System.Web.UI.HtmlTextWriter)
MyBase.AddAttributesToRender(writer)
'add an attribute to the textbox to call client script to check
'keys pressed
writer.AddAttribute("onkeypress", _
"return " & CHECK_KEY_NAME & "( );")
End Sub 'AddAttributesToRender
End Class 'CH05CustomControlNumericInputVB End Namespace
Example 5-16. Numeric input-only text box (.cs)
//---------------------------------------------------------------------------- // // Module Name: CH05CustomControlNumericInputCS // // Description: This class provides a custom control that implements an // input control that only allows numbers to be input. // //**************************************************************************** using System; using System.Text; using System.Web; using System.Web.UI; namespace ASPNetCookbook.CSExamples { public class CH05CustomControlNumericInputCS : System.Web.UI.WebControls.TextBox { // the following constant defines the name of the name of the client-side // JavaScript method used to process keystrokes private const String CHECK_KEY_NAME = "checkKey"; //************************************************************************ // // ROUTINE: OnPreRender // // DESCRIPTION: This routine handles the prerender event for the custom // control. It adds clientside script to process keys // before adding them to the textbox. //------------------------------------------------------------------------protected override void OnPreRender(System.EventArgs e)
{
StringBuilder clientScript = null;
base.OnPreRender(e);
// generate the opening script tag
clientScript = new StringBuilder( );
clientScript.Append("<script language='javascript'> ");
clientScript.Append("<!-- ");
// generate code to check the key pressed
clientScript.Append("function " + CHECK_KEY_NAME + "( ) ");
clientScript.Append("{ ");
clientScript.Append("var key = event.keyCode; ");
clientScript.Append("var processKey = false; ");
clientScript.Append("if ((key >= 0x30) && (key <= 0x39)) ");
clientScript.Append("{ ");
clientScript.Append("processKey = true; ");
clientScript.Append("} ");
clientScript.Append("return(processKey); ");
clientScript.Append("} ");
// generate the closing script tag
clientScript.Append("//--> ");
clientScript.Append("</script> ");
// register script to be output when the page is rendered
Page.RegisterClientScriptBlock(CHECK_KEY_NAME,
clientScript.ToString( ));
} // OnPreRender
//************************************************************************ // // ROUTINE: AddAttributesToRender // // DESCRIPTION: This routine handles the AddAttributeToRender event // for the custom control. It adds the onkeypress // attribute to the textbox to cause processing of all // keys pressed when the textbox has focus. //------------------------------------------------------------------------protected override void AddAttributesToRender(
System.Web.UI.HtmlTextWriter writer)
{
base.AddAttributesToRender(writer);
// add an attribute to the textbox to call client script to check
// keys pressed
writer.AddAttribute("onkeypress", "return " + CHECK_KEY_NAME + "( );");
} // AddAttributesToRender
} // CH05CustomControlNumericInputCS }
Example 5-17. Using the numeric input custom control (.aspx)
<%@ Page Language="vb" AutoEventWireup="false" Codebehind="CH05DisplayControlWIthNumericInputVB.aspx.vb" Inherits="ASPNetCookbook.VBExamples.CH05DisplayControlWIthNumericInputVB" %><%@ Register TagPrefix="ASPCookbook" Namespace="ASPNetCookbook.VBExamples"
Assembly="ASPNetCookbookVB" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>Custom Control With Numeric Input</title> <link rel="stylesheet" href="css/ASPNetCookbook.css"> </head> <body leftmargin="0" marginheight="0" marginwidth="0" topmargin="0"> <form id="frmCustomControl" method="post" runat="server"> <table width="100%" cellpadding="0" cellspacing="0" border="0"> <tr> <td align="center"> <img src="images/ASPNETCookbookHeading_blue.gif"> </td> </tr> <tr> <td class="dividerLine"> <img src="images/spacer.gif" height="6" border="0"></td> </tr> </table> <table width="90%" align="center" border="0"> <tr> <td><img src="images/spacer.gif" height="10" border="0"></td> </tr> <tr> <td align="center" class="PageHeading"> Custom Numeric Input Control (VB) </td> </tr> <tr> <td><img src="images/spacer.gif" height="10" border="0"></td> </tr> <tr bgcolor="#ffffcc"> <td align="center"><ASPCookbook:CH05CustomControlNumericInputVB
id="ccNumericInput" runat="server"
Columns="10" MaxLength="10" />
</td> </tr> <tr> <td align="center"> <br> <asp:ImageButton ID="btnSubmit" Runat="server" ImageUrl="images/buttons/button_submit.gif" /> </td> </tr> </table> </form> </body> </html>