92 Part I Fundamentals Controls and Events The PalindromeCheckerRenderedControl shows how to render control content differently de-pending on the state of the Text property.. Select
Trang 1Chapter 4 Custom Rendered Controls 91
4 Build the project by selecting Build, Build Solution from the main menu
5 Add the PalindromeCheckerRenderedControl to the toolbox if it’s not already there
Visual Studio should add the PalindromeCheckerRenderedControl to the Toolbox If
not, you can add it manually Click the right mouse button on the toolbox and select
Choose Item Use the Browse button to fi nd the CustomControlLib.DLL assembly and
select it Visual Studio will load the new control in the toolbox
6 Add a page to use the palindrome checker control Add a new Web Form to the
ControlORama project and name it UsePalindromeCheckerControls.aspx Drag the PalindromeCheckerRenderedControl and drop it on the page Add a TextBox and a but-
ton so you can add a palindrome to the control and check it
7 Add a handler for the button Double-click on the button Visual Studio will add a
han-dler to the page In the hanhan-dler, set the PalindromeCheckerRenderedControl’s text
prop-erty to the TextBox.Text property
public partial class UsePalindromeCheckerControls : System.Web.UI.Page
Trang 292 Part I Fundamentals
Controls and Events
The PalindromeCheckerRenderedControl shows how to render control content differently
de-pending on the state of the Text property While that’s a very useful thing in itself, it’s often
helpful to also alert the host page to the fact that a palindrome was found You can do this
by exposing an event from the control
Most of ASP.NET’s standard server-side controls already support events You’ve already seen how the Button control sends an event to the host page when it is clicked You can
actually do this type of thing with any control Let’s add a PalindromeFound event to the PalindromeCheckerRenderedControl
Adding a PalindromeFound event
1 Open the PalindromeCheckerRenderedControl.cs fi le To add a PalindromeFound event,
type in the following line:
public class PalindromeCheckerRenderedControl : WebControl
{
public event EventHandler PalindromeFound;
// Other palindrome control code goes here
}
Trang 3Chapter 4 Custom Rendered Controls 93
2 Once hosts have subscribed to the event, they’ll want to know when the event fi res To
do this, fi re an event on detecting a palindrome The best place to do this is within the
Text property’s setter Add the boldfaced lines of code to the palindrome’s Text
prop-erty and rebuild the project:
3 Now wire the event in the host page Remove the current instance of the
PalindromeCheckerRenderedControl from the page and drop a new instance on the
page This will refresh the CustomControlLib.DLL assembly so the changes (the new
event) will appear in Visual Studio Select the PalindromeCheckerRenderedControl on
the page and click the Events button (the little lightning bolt) in the property page in
Visual Studio Double-click on the text box next to the PalindromeFound event Visual
Studio will create an event handler for you
Trang 494 Part I Fundamentals
4 Respond to the PalindromeFound event The example here simply prints some text out
to the browser using Response.Write
public partial class UsePalindromeCheckerControls : System.Web.UI.Page
protected void PalindromeCheckerControl1_PalindromeFound(
object sender, EventArgs e)
{
Response.Write("The page detected a PalindromeFound event");
}
}
Trang 5Chapter 4 Custom Rendered Controls 95
Run the page You should see something like the following when you type a palindrome:
Now that the control renders palindromes correctly and has an event, let’s take a closer look
at the parameter passed in during the call to Render: HtmlTextWriter
HtmlTextWriter and Controls
Go back and review the control’s RenderContents method for a minute Notice that the RenderContents method places literal font tags to change the color of the palindrome text
While this is certainly effective, this technique has a couple of downsides For example, HTML
is defi ned by multiple standards That is, browsers running both HTML version 3.2 and sion 4.0 occur in nature Certain HTML elements have changed between version 3.2 and version 4.0 If you render all your HTML directly expecting requests from a certain kind of browser, your users may be taken by surprise if they browse to your page with a new browser that interprets HTML differently
Trang 6ver-96 Part I Fundamentals
Note The NET framework includes multiple versions of the HtmlTextWriter class:
Html32TextWriter, HtmlTextWriter, XhtmlTextWriter, and ChtmlTextWriter When a request comes
from a browser, it always includes some header information indicating what kind of browser made the request Most browsers these days are capable of interpreting the current version of HTML In this case, ASP.NET passes in a normal HtmlTextWriter into the RenderControl method
However, if you happen to get a request from a lesser browser that understands only HTML 3.2, ASP.NET passes in an Html32TextWriter The classes are similar as far as their use and may be in-
terchanged Html32TextWriter emits certain tags (such as table tags) in HTML 3.2 format, while HtmlTextWriter emits the same tags in HTML4.0 format Information within machine.confi g and
the browser capabilities confi guration help ASP.NET fi gure out what kind of HtmlTextWriter to
use The browser capability information deduced by the ASP.NET runtime may be used for more than simply selecting the correct HtmlTextWriter The Request property (available as part of the HttpContext and the Page) includes a reference to the Browser object This object includes a
number of fl ags indicating various pieces of information, such as the type of browser making the request, whether the browser supports scripting, and the name of the platform the browser is running on This information comes down as part of the headers included with each request The ASP.NET runtime runs the headers against some well-known regular expressions within the con-
fi guration fi les to fi gure out the capabilities For example, here’s a short listing illustrating how to
fi gure out if the browser making the request supports Frames:
public class TestForFramesControl : Control
To get a feel for using the more advanced capabilities of HtmlTextWriter, replace the
hard-coded font tags in the RenderContents method of the PalindromeCheckerRenderedControl
with code that uses the HtmlTextWriter facilities
Use the HtmlTextWriter
1 Open the PalindromeCheckerRenderedControl.cs fi le
2 Update the RenderContents method to use the HtmlTextWriter methods Use
HtmlTextWriter.RenderBeginTag to start a font tag and a bold tag Use HtmlTextWriter AddStyleAttribute to change the color of the font to blue
protected override void RenderContents(HtmlTextWriter output)
{
if (this.CheckForPalindrome())
Trang 7Chapter 4 Custom Rendered Controls 97
The HtmlTextWriter class and the enumerations include support to hide all the oddities of
switching between HTML 3.2 and 4.0 Listing 4-5 shows how a table would be rendered using
an HTML 4.0–compliant response Listing 4-6 shows how a table would be rendered using an HTML 3.2–compliant response
LISTING 4-5 HTML 4.0 Rendered Control
<br />
<br />
This is a palindrome: <br>
<b><font>Do geese see god?</font></b><br>
<table width="50%" border="1" style="color:blue;">
<b><font>Do geese see god?</font></b><br>
<table width="50%" border="1">
Trang 898 Part I Fundamentals
Controls and ViewState
Before leaving rendered controls, let’s take a look at the issue of control state If you go back
to some of the classic ASP examples from earlier chapters, you may notice something concerting about the way some of the controls rendered after posting back After you select something in the combo box and make a round-trip to the server, by the time the response gets back, the controls (especially selection controls) have lost their state Recall that the basic Web programming model is all about making snapshots of the server’s state and displaying them using a browser We’re essentially trying to perform stateful user interface (UI) develop-ment over a disconnected protocol
ASP.NET server-side controls include a facility for holding onto a page’s visual state—it’s
a property in the Page named ViewState, and you can easily access it any time you need ViewState is a dictionary (a name-value collection) that stores any serializable object
Most ASP.NET server-side controls manage their visual state by storing and retrieving items
in the ViewState For example, a selection control might maintain the index of the selected
item between posts so that the control knows which item has its selected attribute assigned
The entire state of a page is encoded in a hidden fi eld between posts For example, if you browse to an ASPX page and view the source code coming from the server, you’ll see the
ViewState come through as a BASE 64–encoded byte stream
To get a feel for how ViewState works, add some code to keep track of the palindromes that
have been viewed through the control
Using ViewState
1 Open the PalindromeCheckerRenderedControl.cs fi le
2 Add System.Collections to the list of using directives
3 Add an ArrayList to the control to hold the viewed palindromes Update the Text
prop-erty’s setter to store text in the view state if the text is a palindrome
public class PalindromeCheckerRenderedControl : WebControl
{
public event EventHandler PalindromeFound; // public event
ArrayList alPalindromes = new ArrayList();
[Bindable(true)]
Trang 9Chapter 4 Custom Rendered Controls 99
4 Add a method to render the palindrome collection as a table and update the
RenderContents method to render the viewed palindromes
protected void RenderPalindromesInTable(HtmlTextWriter output)
Trang 105 Build and run the application When you surf to the page holding the palindrome
checker, you should see the previously found palindromes appearing in the table:
Trang 11Chapter 4 Custom Rendered Controls 101
Now that the control is storing more information in the ViewState, the HTML response due to
postbacks will increase in size as the _VIEWSTATE fi eld within the response grows Add a few more palindromes to the page, viewing the source that’s sent to the browser each time You’ll see the VIEWSTATE hidden fi eld grow in size with each postback The caveat here is that in-troducing controls that use view state will increase the size of the HTTP payload coming back
to the browser Use the view state judiciously as overuse can bog down a site’s performance
Summary
ASP.NET’s Page infrastructure is set up so that each page is broken down into smaller
compo-nents (server-side controls) that are responsible for rendering a small amount of HTML into the page’s output stream After reading this chapter, you probably have a good idea as to how some of the standard ASP.NET controls are rendered Button controls render as an input
tag with a type of “submit.” TextBox controls render as an input tag with a type of “text.” You
can actually see how each of the controls in a page renders by viewing the HTML that comes back to the browser
Of course, because ASP.NET’s Page infrastructure is set up this way, it leaves the door open
for custom User controls In this chapter, we looked at rendered custom controls Custom controls that render have the ability to squirt anything they want into the output bound for the browser Custom rendered controls usually manage a set of properties, fi re events to their hosts, and render snapshots of themselves to their hosts In this chapter, we built a pal-indrome checker as an example Next, we’ll see examples of the other kind of control you can create for your own needs—composite-style “User” controls
Chapter 4 Quick Reference
Create a custom control that takes
over the rendering process
Derive a class from System.Web.UI.Control.
Override the RenderContents method.
Visual Studio includes a project type, ASP.NET ServerControl, that fi ts the bill.
Add a custom control to the toolbox Show the toolbox if it’s not already showing by selecting View,
Toolbox from the main menu.
Click the right mouse button anywhere in the toolbox.
Select Choose Items from the local menu.
Choose a control from the list OR
Browse to the assembly containing the control.
Trang 12102 Part I Fundamentals
Change the properties of controls
on a page
Make sure the page editor is in Design mode.
Highlight the control whose property you want to change.
Select the property to edit in the Properties window.
Manage events fi red by controls on
a page
Make sure the page editor is in Design mode.
Highlight the control containing the event you want your page to handle.
Select the event in the event window (you may highlight it by pressing the lightning bolt button in the Properties window).
Double-click in the combo box next to the event to have Visual Studio insert the given handler for you
OR Insert your own event handler name in the fi eld next to the event name.
Store view state information that
lives beyond the scope of the page
Use the ViewState property of the control (a name-value dictionary)
that contains serializable types.
Just be sure to use the same index to retrieve the information as you
do to store the information.
Write browser version–independent
rendering code
Use the HtmlTextWriter tag-rendering methods for specifi c tags
in-stead of hard-coding them The RenderContents method will have the
correct HtmlTextWriter based on header information coming down
from the browser
Trang 13103
Chapter 5
Composite Controls
After completing this chapter, you will be able to
Create a binary composite custom control
Create a composite User control
Use both kinds of controls in an application
Recognize when each kind of control is appropriate
The last chapter covered the details of controls that do custom rendering, and this chapter covers the other kind of control—composite controls ASP.NET defi nes two broad categories
of composite controls—binary custom controls and user custom controls Each type of posite control has advantages and disadvantages, which we’ll discuss First, let’s explore the primary differences between rendered controls and composite-style controls
Composite Controls versus Rendered Controls
Recall that custom rendered controls completely form and tailor the HTML going back to the client via the System.Web.UI.Control.RenderControl method Custom rendered controls take
over the entire rendering process With custom rendered controls, you have extraordinary
fl exibility and power over the HTML emitted by your Web site—all the way down to the vidual control level
However, with that power and fl exibility also comes the need to keep track of an enormous amount of detail For example, if you were to add an input button to a custom rendered control, you’d need to insert the correct HTML to describe the button within the response stream heading back to the client Things get even more diffi cult when you decide to add more complex controls such as selection controls that may need to track collections of items Even though input buttons and selection controls are easy to describe in HTML, we’ve seen that ASP.NET already includes server-side control classes that render the correct tags The standard ASP.NET controls greatly simplify user interface (UI) programming for Web forms Composite controls take advantage of these server-side controls that have already been writ-ten Composite controls are composed from other controls To illustrate the utility of compos-
ite controls, imagine you’re working on a number of projects whose login screens require a similar look and feel On the one hand, you’ve already seen that it’s fairly easy to build Web forms in Visual Studio However, if you run into a situation that requires the same group of controls to appear together in several instances, it’s pretty tedious to recreate those pages repeatedly ASP.NET solves this problem with composite controls
Trang 14104 Part I Fundamentals
If you need common login functionality to span several Web sites, you might group user name/password labels and text boxes together in a single control Then when you want to use the login page on a site, you simply drop the controls en masse on the new form The
controls (and the execution logic) instantly combine so you don’t need to keep writing the same HTML over and over
Note Beginning with version 2.0, ASP.NET includes a set of login composite controls so you don’t need to write new ones from scratch However, they are mentioned here because they rep- resent an excellent illustration for the power of composite controls
Let’s begin by looking at custom composite controls
Custom Composite Controls
In Chapter 4, we saw how binary custom controls render custom HTML to the browser The factor distinguishing this kind of control most is that these controls override the
RenderContents method Remember, the System.Web.UI.Page class manages a list of
server-side controls When ASP.NET asks the whole page to render, it goes to each control on the page and asks it to render In the case of a rendering control, the control simply pushes some text into the stream bound for the browser Likewise, when the page rendering mechanism hits a composite-style control, the composite control walks its list of child controls, asking each one to render—just as the Page walks its own list of controls
Composite controls may contain an arbitrary collection of controls (as many children as memory will accommodate), and the controls may be nested as deeply as necessary Of course, there’s a practical limit to the number and depth of the child controls Adding too many controls or nesting them too deeply will add complexity to a page, and it may become unsightly In addition, adding too many nested controls will greatly inhibit the performance
of the application It does take time to walk the control collection and have each one render
In Chapter 4, we created a control that checked for palindromes When the control’s Text
property was set to a palindrome, the control rendered the palindrome in blue text, added it
to an ArrayList, and then rendered the contents of the palindrome collection as a table Let’s
build a similar control—however, this time it will be a composite control
The palindrome checker as a composite custom control
1 Open the ControlORama project Highlight the CustomControlLib project in the Solution
Explorer Click the right mouse button on the project node and select Add, New Item
Create a new class and name the source fi le PalindromeCheckerCompositeControl.cs Use
the ASP.NET Server Control template (as you did with the PalindromeCheckerRenderedControl from Chapter 4)
Trang 15Chapter 5 Composite Controls 105
2 After Visual Studio creates the code, do the following:
Edit the code to change the derivation from WebControl to CompositeControl
Deriving from the CompositeControl also adds the INamingContainer interface to
the derivation list (INamingContainer is useful to help ASP.NET manage unique
IDs for the control’s children.)
Add the PalindromeFound event that the host page may use to listen for
palin-drome detections
Remove the RenderContents method
Add four member variables—a TextBox, a Button, a Label, and a LiteralControl
The code should look something like this when you’re fi nished:
public class PalindromeCheckerCompositeControl :
CompositeControl
{
protected TextBox textboxPalindrome;
protected Button buttonCheckForPalindrome;
protected Label labelForTextBox;
protected LiteralControl literalcontrolPalindromeStatus;
public event EventHandler PalindromeFound;
// RenderContents method removed.
}
Leave the Text property intact We’ll still need it in this control
The control is very much like the one in Chapter 4 However, this version will include the palindrome TextBox, the Button to invoke palindrome checking, and will contain a
literal control to display whether or not the current property is a palindrome
3 Borrow the StripNonAlphanumerics and CheckForPalindrome methods from the