User Controls and Custom Server Controls, Part 2
|
Related Reading
ASP.NET in a Nutshell |
Editor's note: Part 2 in this series of excerpts from ASP.NET in a Nutshell focuses on ASP.NET custom server controls.
Custom Server Controls
For the reasons cited earlier in the chapter, user controls are not always the ideal choice for reuse. They tend to be very good for quickly reusing existing user interface elements and code, but are not especially useful for developing reusable building blocks for multiple web applications. This is where custom server controls come in.
A custom server control is, in its essence, a class that derives from either the Control or WebControl class of the System.Web.UI namespace, or from one of the classes that derive from these controls. Custom server controls can be used in your ASP.NET Web Forms pages in very much the same way you use the built-in server controls that come with ASP.NET. There are two primary categories of custom server controls:
- Rendered controls
- Rendered controls consist largely of custom rendering of the text, tags, and any other output you desire, which may be combined with the rendered output of any base class your control is derived from. Rendered controls override the Render method of the control they derive from. This method is called automatically by the page containing the control when it's time for the control output to be displayed.
- Compositional controls
- Compositional controls get their name from the fact that they are composed of existing controls whose rendered output forms the UI of the custom control. Compositional controls create their constituent controls by overriding the CreateChildControls method of the control they derive from. This method, like the Render method, is automatically called by ASP.NET at the appropriate time.
When designing a new custom server control, you need to consider some issues to decide which type of control to create:
|
In This Series
User Controls and Custom Server Controls, Part 4
User Controls and Custom Server Controls, Part 3
User Controls and Custom Server Controls, Part 1 |
- Does one existing control provide most, but not all, of the functionality you desire? Then a rendered control that derives from that control may be the right choice.
- Could the desired functionality be provided by a group of existing controls? Then a compositional control may be a great way to reuse those controls as a group.
- Do you want to do something that is completely beyond any existing control? Then you may want to derive your control from the
Controlclass and override the Render method to create your custom output.
Note that by default, custom server controls expose all public members of the class from which they are derived. This exposure is important to consider when designing a control for use by other developers if you want to limit the customizations they can make. For instance, you might not want developers to change the font size of your control. In such a case, you should avoid deriving from a control that exposes that property.
Rendered Controls
Perhaps the best way to understand the process of creating a rendered custom server control is to see one. Example 6-4 shows a class written in Visual Basic .NET that implements a custom navigation control with the same functionality as the Nav.ascx user control discussed earlier in this chapter. Unlike the user control, which has the linked pages and images hardcoded into the control itself, the custom control in Example 6-4 gets this information from an XML file.
Example 6-4: NavBar.vb
Imports Microsoft.VisualBasic
Imports System
Imports System.Data
Imports System.Drawing
Imports System.IO
Imports System.Text
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Namespace aspnetian
Public Class NavBar
Inherits Panel
Private NavDS As DataSet
Private _showDividers As Boolean = True
Public Property ShowDividers( ) As Boolean
Get
Return _showDividers
End Get
Set
_showDividers = value
End Set
End Property
Sub NavBar_Load(sender As Object, e As EventArgs) Handles MyBase.Load
LoadData( )
End Sub
Protected Overrides Sub Render(Writer As HtmlTextWriter)
Dim NavDR As DataRow
Dim RowNum As Integer = 1
Dim SB As StringBuilder
MyBase.RenderBeginTag(Writer)
MyBase.RenderContents(Writer)
Writer.Write("<hr width='80%'>" & vbCrLf)
For Each NavDR In NavDS.Tables(0).Rows
SB = new StringBuilder( )
SB.Append(vbTab)
SB.Append("<a href=""")
SB.Append(NavDR("url"))
SB.Append(""" onmouseover=""")
SB.Append("img")
SB.Append(RowNum.ToString( ))
SB.Append(".src='")
SB.Append(NavDR("moimageUrl"))
SB.Append("';""")
SB.Append(" onmouseout=""")
SB.Append("img")
SB.Append(RowNum.ToString( ))
SB.Append(".src='")
SB.Append(NavDR("imageUrl"))
SB.Append("';""")
SB.Append(" target='")
SB.Append(NavDR("targetFrame"))
SB.Append("'>")
SB.Append(vbCrLf)
SB.Append(vbTab)
SB.Append(vbTab)
SB.Append("<img border='0' align='absMiddle' alt='")
SB.Append(NavDR("text"))
SB.Append("' src='")
SB.Append(NavDR("imageUrl"))
SB.Append("' id='")
SB.Append("img")
SB.Append(RowNum.ToString( ))
SB.Append("' name='")
SB.Append("img")
SB.Append(RowNum.ToString( ))
SB.Append("'></a>")
SB.Append(vbTab)
SB.Append("<a href=""")
SB.Append(NavDR("url"))
SB.Append(""" onmouseover=""")
SB.Append("img")
SB.Append(RowNum.ToString( ))
SB.Append(".src='")
SB.Append(NavDR("moimageUrl"))
SB.Append("';""")
SB.Append(" onmouseout=""")
SB.Append("img")
SB.Append(RowNum.ToString( ))
SB.Append(".src='")
SB.Append(NavDR("imageUrl"))
SB.Append("';""")
SB.Append(" target='")
SB.Append(NavDR("targetFrame"))
SB.Append("'>")
SB.Append(NavDR("text"))
SB.Append("</a>")
SB.Append(vbCrLf)
If _showDividers = True Then
SB.Append("<hr width='80%'>")
Else
SB.Append("<br/><br/>")
End If
SB.Append(vbCrLf)
Writer.Write(SB.ToString( ))
RowNum += 1
Next
MyBase.RenderEndTag(Writer)
End Sub
Protected Sub LoadData( )
NavDS = New DataSet( )
Try
NavDS.ReadXml(Page.Server.MapPath("NavBar.xml"))
Catch fnfEx As FileNotFoundException
CreateBlankFile( )
Dim Html As String
Html = "<br>No NavBar.xml file was found, so one was " & _
"created for you. Follow the directions in the file " & _
"to populate the required fields and, if desired, " & _
"the optional fields."
Me.Controls.Add(New LiteralControl(Html))
End Try
End Sub
Public Sub CreateBlankFile( )
'Code to create a blank XML file with the fields used by
' the control. This code is included as a part of the file
' NavBar.vb, included with the sample files for the book.
End Sub
End Class
End Namespace
The real meat of the NavBar control begins with the class declaration, which uses the Inherits keyword to declare that the control derives from the Panel control. This gives the control the ability to show a background color, to be hidden or shown as a unit, and to display the contents of its begin and end tags as part of the control.

