Practical ASP.NET

Customizing the Login Control

By converting composite controls into their templates, you gain full control over the makeup of the control and individual controls within it.

I had a client who was building their own copy of some ASP.NET Login controls, beginning with the Login control. When I asked why they were doing this, my client said that they needed to make the controls look like the equivalent versions on their old HTML pages. Among other issues, the login process needed to include a dropdown list control that allowed the user to specify which of the company's regions they were logging into. Since my client had already committed a lot of time and effort into the project, I didn't want to tell them that they could have enabled everything they wanted with just one mouse click.

Converting to and from Templates
The Login control consists of multiple other controls (as do some other controls, including the PasswordRecovery and ChangePassword controls). When a page holding the Login control shows up in the browser, the Login control turns into multiple HTML elements: a table with five rows (each with one or two cells), plus some label and input elements.

Even in design view, you can see that a Login control consists of two textboxes, a button and a checkbox (this type of control is called a "composite" control). Not visible is the label for displaying messages when the user fails to login successfully. The figure below shows a default ASP.NET Login control, which is a single server-side control with multiple client-side components.


[Click on image for larger view.]
Figure 1.

Fortunately, the Login control can be broken into its individual controls: Just right-mouse click on the control and from the popup menu, select Convert To Template. This option is also available from the control's SmartTag. As shown below, you can now work with the individual components of the control.


[Click on image for larger view.]
Figure 2.

In source view, you can see the results of the change as a new set of tags. Before being converted to a template, the Login control is represented by this single tag:

‹asp:Login ID="Login1" runat="server" Width="359px"›
‹/asp:Login›

Even as a composite control, you can access the individual controls in the Login control using the control's FindControl method. For instance, if you're preloading the UserName textbox and, as a result, want to place the user's cursor in the Password textbox, you can retrieve that textbox and set the cursor with this code:

Me.Login1.FindControl("Password").Focus()

After being converted, the number of tags in source view increases dramatically to explicitly represent every control within the Login control:

‹asp:Login ID="Login1" runat="server" Width="359px"›
‹LayoutTemplate›
‹table border="0" cellpadding="1" cellspacing="0"
style="border-collapse:collapse;"›
…many, many more tags…
‹/table›
‹/LayoutTemplate›
‹/asp:Login›

Feel free to experiment with this feature: Any code that you have in the page that works with the control before you convert it will work after you convert it. And, if you decided you were sorry you converted your control, you can right-mouse click in any part of the control's table and select Reset (or, again, use the SmartTag).

Just as an aside: Converting the Login control into a template lets you use it in an UpdatePanel.

Customizing the Control
You can now modify your Login control any way that you want, within a very few limits. The primary limitation is that you must have two controls that implement the ITextControl interface, to ensure that the controls have a Text property. One control must have its ID property set to "UserName" and the other must have its ID property set to "Password." You also need a Button of some type (LinkButton, ImageButton) with its CommandName property set to "Login," or to whatever value is returned by the Login control's LoginButtonCommandName property.

My client's changes could have been implemented by converting the Login control into a template and dragging a DropDownList to the resulting table. In the control's Authenticate event, however, my client would need to be able to access the control to pass it to their custom authentication code.

Fortunately, accessing a control in the template is easy to do. Using the FindControl method on the Login control lets you get a reference to any control within the template. This example retrieves a DropDownList with an ID property set to "RegionDropDown" and extracts its SelectedValue:

Dim cnt As Control
Dim ddlRegion As DropDownList
Dim RegionCode As String
cnt = Me.Login1.FindControl("RegionDropDown")
If cnt IsNot Nothing Then
ddlRegion = CType(cnt, DropDownList)
RegionCode = ddlRegion.SelectedValue
End If

Had my client only spoken to me, I could have saved them a lot of time. Or, alternatively (and better yet), they could have given me a lot less money to deliver the control they wanted.

About the Author

Peter Vogel is a system architect and principal in PH&V Information Services. PH&V provides full-stack consulting from UX design through object modeling to database design. Peter tweets about his VSM columns with the hashtag #vogelarticles. His blog posts on user experience design can be found at http://blog.learningtree.com/tag/ui/.

comments powered by Disqus
Upcoming Events

.NET Insight

Sign up for our newsletter.

I agree to this site's Privacy Policy.