|
An ordinary VB developer shares his own successes and failures |
|
| Home News Articles Resources Tips Downloads About me | ||
Inheriting An ASP.NET Server ControlHow to easily customize an ASP.NET server control by deriving from it.After developing several ASP.NET WebForms applications, I have to say that ASP.NET is a great framework. Despite the fact that my knowledge about the ASP.NET architecture is near to nothing, I was still able to develop something useful (I hope ).
For the most part, my ASP.NET applications are simple,
ad-hoc front-ends to some back-end functionality (see
http://www.nrsr.sk/bin/net/nrozprava/ as an example). I
didn't need to use any sophisticated custom controls; just a
Sometimes, however, I needed to extend a built-in Let's illustrate the concept with an example: Your ASP.NET application should display a form with several buttons on it. When clicked, some of the buttons should execute the associated (server-side) event handler code directly. Some of the buttons, however, have to display a confirmation prompt on the client browser, allowing the user to cancel the initiated execution of the command.
Because the buttons that should display the client-side
confirmation are...well, buttons, it is natural (IMHO) to
derive a new class from the existing
Namespace LaMarvin.Samples.Web.DerivingBuiltinControls
Public Class PromptButton
Inherits System.Web.UI.WebControls.Button
' Our confirmation message or Nothing if no
' confirmation prompt should be displayed on the client.
Private _ConfirmMessage As String = String.Empty
Public Overridable Property ConfirmMessage() As String
Get
Return _ConfirmMessage
End Get
Set(ByVal Value As String)
_ConfirmMessage = Value
End Set
End Property
Protected Overrides Sub AddAttributesToRender( _
ByVal writer As System.Web.UI.HtmlTextWriter)
If _ConfirmMessage.Length > 0 Then
writer.AddAttribute("onclick", _
"return confirm('" + _ConfirmMessage + "');")
End If
MyBase.AddAttributesToRender(writer)
End Sub
End Class
End Namespace
First, we've declared the _ConfirmMessage member variable
and the public ConfirmMessage accessor property.
Second, we've overridden the
In order to use the <%@ Register TagPrefix = "dc" Namespace = "LaMarvin.Samples.Web.DerivingBuiltinControls" Assembly = "DerivingBuiltinControls" %>The TagPrefix "dc" is an arbitrary string that is an alias
for the associated namespace (as declared by the Namespace
attribute).
The
The following fragment illustrates how the <dc:PromptButton id="WithPrompt" runat="server" Text="With Prompt" ConfirmMessage="Are you sure?" />It is important to note that the string after the tag prefix gets combined with the associated namespace to form the fully qualified type name - LaMarvin.Samples.Web.DerivingBuiltinControls.PromptButton
in this case.
That's all if you're adding your derived controls through the HTML view of the VS.NET WebForms designer. You can also add your derived control to the WebForms designer toolbox so you can create the control's instances using drag & drop from the toolbox. Just right-click the toolbox, choose 'Add/Remove Items...' and browse for the assembly.dll file (it's in the project's bin subdirectory).
In order to better support the design-time experience, you might want to customize the initial HTML code that is generated by the designer when you place a new instance of your control onto a form.
You can do this by applying the
<ToolboxData("<{0}:PromptButton runat=""server"" ConfirmMessage=""Hello!"" />")> _
Public Class PromptButton
Inherits System.Web.UI.WebControls.Button
Note that you must always include the string "{0}", which
gets replaced be the actual tag prefix used within the page.
Also you have to include the runat = "server" attribute,
otherwise the designer won't be able to instantiate your
control.
Beware, however, that when you change the
Despite this small annoyance, deriving from an ASP.NET server control might be useful technique if you need functionality that "is-a" extension of an existing server control. Note to cautious readers ...There are two quite serious problems with the above-describedPromptButton implementation.
Take a look at the code once again. Can you spot the problems? Here are some hints...
Nothing to the
ConfirmMessage property (in the Page_Load event, for
example), System.NullReferenceException will be thrown in
the PromptButton.AddAttributesToRender method.
The second one, however, is more dangerous, because it
doesn't manifest so "loudly". That is, when the
Fortunately, the cure is easy - here is
a more robust
implementation of the
Imports System.ComponentModel
Imports System.Web.UI.WebControls
<ToolboxData("<{0}:PromptButton runat=""server"" ConfirmMessage=""Hello!"" />")> _
Public Class PromptButton
Inherits Button
Private _ConfirmMessage As String = String.Empty
' Our confirmation message or String.Empty if no
' confirmation prompt should be displayed on the client.
Public Overridable Property ConfirmMessage() As String
Get
Return _ConfirmMessage
End Get
Set(ByVal Value As String)
_ConfirmMessage = Value
' Test for Nothing on this one place, instead of
' here and there throughout the implementation.
If _ConfirmMessage Is Nothing Then
_ConfirmMessage = String.Empty
End If
End Set
End Property
Protected Overrides Sub AddAttributesToRender( _
ByVal writer As System.Web.UI.HtmlTextWriter)
If _ConfirmMessage.Length > 0 Then
' Change embedded apostrophes to corresponding
' escape sequences.
Dim EscapedMessage As String = Replace(_ConfirmMessage, "'", "\'")
writer.AddAttribute("onclick", _
"return confirm('" & EscapedMessage & "');")
End If
MyBase.AddAttributesToRender(writer)
End Sub
End Class
Would you say that a few simple lines of the PromptButton
code could break the whole application?
© Palo Mraz, Tuesday, October 07, 2003 |
||
|
|
||
| ©2003-2007 Palo Mraz. All Rights Reserved. See my 'new browser window' policy | ||