ASP.NET 4 Unleashed

To this point, you've built custom controls from scratch. However, in some cases, creating a new control out of existing controls is much easier. For example, imagine that you want to create a custom control that displays a login form. You want the control to display both username and password text boxes. This control is a good candidate for a composite control.

Listing 28.28 contains the code for a composite Login control.

Listing 28.28 Login.vb

Imports System Imports System.Web Imports System.Web.UI Imports System.Web.UI.WebControls Namespace myControls Public Class Login Inherits Control Implements INamingContainer Public Property Username As String Get Me.EnsureChildControls() Return CType( Controls( 2 ), TextBox ).Text End Get Set Me.EnsureChildControls() CType( Controls( 2 ), TextBox ).Text = Value End Set End Property Public Property Password As String Get Me.EnsureChildControls() Return CType( Controls( 5 ), TextBox ).Text End Get Set Me.EnsureChildControls() CType( Controls( 5 ), TextBox ).Text = Value End Set End Property Protected Overrides Sub CreateChildControls() Me.Controls.Add( New LiteralControl( "<div style=""border: 5px " & _ "inset #cccccc;background-color:#eeeeee;width:50%;padding:10px"">" ) ) ' Add Username Me.Controls.Add( New LiteralControl( "<b>Username:</b> " ) ) Me.Controls.Add( New TextBox ) Me.Controls.Add( New LiteralControl( "<p>" ) ) ' Add Password Dim txtPass As New TextBox Me.Controls.Add( New LiteralControl( "<b>Password:</b> " ) ) txtPass.TextMode = TextBoxMode.Password Me.Controls.Add( txtPass ) Me.Controls.Add( New LiteralControl( "<p>" ) ) ' Add Submit Button Dim btnButton As New Button btnButton.Text = "Login!" Me.Controls.Add( btnButton ) Me.Controls.Add( New LiteralControl( "</div>" ) ) End Sub End Class End Namespace

The C# version of this code can be found on the CD-ROM.

The bulk of Listing 28.28 is contained in the CreateChildControls subroutine. This subroutine adds username TextBox , password TextBox , and Button controls to the Controls collection of the Login control.

Notice that the Login control does not contain a Render method. It isn't necessary because all the rendering is taken care of by the child controls. The child controls even automatically handle preserving view state. If you enter a username in the username control, the username is preserved between form posts.

The current values of the username and password TextBox controls are exposed through two properties: Username and Password . Because these properties are declared with the Public modifier, you can read and set them from within an ASP.NET page.

There's one final thing you should notice about Listing 28.28. The control implements the INamingContainer interface, which does not define any methods that you must implement. This interface creates a new ID namespace within a page's control hierarchy; it prevents naming conflicts when the Login control is instantiated more than once. You should always implement the interface when building compositional controls.

The page in Listing 28.29 illustrates how you can use the Login control within an ASP.NET page.

Listing 28.29 DisplayLogin.aspx

<%@ Register TagPrefix="myControls" Namespace="myControls" Assembly="Login"%> <Script Runat="Server"> Sub Page_Load If IsPostBack Then lblMessage.Text = "Hi " & ctrlLogin.Username lblMessage.Text &= ", your password is: " lblMessage.Text &= ctrlLogin.Password End If End Sub </Script> <html> <head><title>DisplayLogin.aspx</title></head> <body> <form Runat="Server"> <myControls:Login ID="ctrlLogin" Runat="Server"/> <p> <asp:Label ID="lblMessage" EnableViewState="False" Font-Size="18pt" Runat="Server" /> </form> </body> </html>

The C# version of this code can be found on the CD-ROM.

The page in Listing 28.29 displays the values of the Username and Password properties of the Login control. When the form containing the Login control is submitted, the values of these properties are displayed in a Label control (see Figure 28.3).

Figure 28.3. Displaying the Login control.

Handling Events in a Composite Control

In the preceding section, you created a control that displays a simple login form. You can use the Login control to submit a username and password combination. In this section, you learn how to extend the Login control to handle events, such as the button Click event that occurs when the login form is submitted.

The trick to handling events in a composite control is to use the Visual Basic AddHandler statement, which enables you to associate a subroutine with an event. Listing 28.30 demonstrates how you can use the AddHandler statement with the Login control to associate a subroutine with the button Click event.

Listing 28.30 LoginEvent.vb

Imports System Imports System.Web Imports System.Web.UI Imports System.Web.UI.WebControls Namespace myControls Public Class LoginEvent Inherits Control Implements INamingContainer Sub CheckPassword( s As Object, e As EventArgs ) Dim strUsername, strPassword As String Dim lblLabel As Label strUsername = CTYPE( Controls( 2 ), TextBox ).Text strPassword = CTYPE( Controls( 5 ), TextBox ).Text lblLabel = CTYPE( Controls( 9 ), Label ) If strUsername = "joe" and strPassword = "secret" Then lblLabel.Text = "Welcome Joe!" Else lblLabel.Text = "Invalid Password!" End If End Sub Protected Overrides Sub CreateChildControls() Me.Controls.Add( New LiteralControl( "<div style=""border: 5px " & _ "inset #cccccc;background-color:#eeeeee;width:50%;padding:10px"">" ) ) ' Add Username Me.Controls.Add( New LiteralControl( "<b>Username:</b> " ) ) Me.Controls.Add( New TextBox ) Me.Controls.Add( New LiteralControl( "<p>" ) ) ' Add Password Dim txtPass As New TextBox Me.Controls.Add( New LiteralControl( "<b>Password:</b> " ) ) txtPass.TextMode = TextBoxMode.Password Me.Controls.Add( txtPass ) Me.Controls.Add( New LiteralControl( "<p>" ) ) ' Add Submit Button Dim btnButton As New Button btnButton.Text = "Login!" AddHandler btnButton.Click, AddressOf CheckPassword Me.Controls.Add( btnButton ) Me.Controls.Add( New LiteralControl( "</div>" ) ) ' Add Label Control Dim lblLabel As New Label lblLabel.EnableViewState = False Me.Controls.Add( lblLabel ) End Sub End Class End Namespace

The C# version of this code can be found on the CD-ROM.

In Listing 28.30, the AddHandler statement associates the login form's button Click event with a subroutine named CheckPassword .

The CheckPassword subroutine compares the username and password entered into the form to the username joe and password secret . If you enter joe and secret , the string Welcome Joe! is assigned to a Label control. Otherwise, the string Invalid Password! is assigned to the Label control.

You can test the new Login control, named LoginEvent , by using the page in Listing 28.31.

Listing 28.31 DisplayLoginEvent.aspx

<%@ Register TagPrefix="myControls" Namespace="myControls" Assembly="LoginEvent"%> <html> <head><title>DisplayLoginEvent.aspx</title></head> <body> <form Runat="Server"> <myControls:LoginEvent Runat="Server"/> </form> </body> </html>

The C# version of this code can be found on the CD-ROM.

Категории