Maximizing.ASP.dot.NET.Real.World.ObjectOriented.Development [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Maximizing.ASP.dot.NET.Real.World.ObjectOriented.Development [Electronic resources] - نسخه متنی

Jeffrey Putz

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید






Composite Controls


Because ASP.NET has so many useful controls, you might rightfully feel that there's no reason to reinvent the wheel with your own control implementation. Instead, a combination of controls might accomplish what you're after. Fortunately you can build composite controls to do just that. If you've ever ventured into the world of Windows forms, building a composite control will seem very familiar to you.

Building a composite control is simply a matter of instantiating existing controls and adding them to the Controls property of the base CompositeControl class. In fact, the first requirement to build a composite control is that your class must inherit from CompositeControl. You don't need to choose between the three choices we mentioned for our from-scratch server control.

The second requirement is to override CompositeControl's CreateChildControls() method. This is where the real magic happensit's where we create, name, and add controls to the Controls property of the base CompositeControl class (the property happens to be of the type ControlCollection).

Let's build a simple composite control that has little to no real use but that shows how easy it is to build a composite control. Let's say we need a TextBox, a Label, and a Button control. Clicking on the button should cause the text in the TextBox to display in the label.

Using what we know about class design and event handlers, we can quickly build the class. We'll need private variables to hold each of our three controls. We'll need an event handler that will copy the text of the TextBox to the Text property of the label. Finally, we'll need a place to create all of these controls, and that place is of course the CreateChildControls() method we mentioned earlier. Listing 9.10 shows the entire class (as well as its use in a page), while Figure 9.3 shows how the controls will be rendered in the browser.

Listing 9.10. A simple composite control

C#


using System;
using System.Collections.Specialized;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace SimpleComposite
{
public class MyCompositeControl : CompositeControl
{
private TextBox _textBox;
private Label _label;
private Button _button;
protected override void CreateChildControls()
{
_textBox = new TextBox();
_textBox.ID = "MyTextBox";
this.Controls.Add(_textBox);
_label = new Label();
_label.ID = "MyLabel";
this.Controls.Add(_label);
_button = new Button();
_button.ID = "MyButton";
_button.Text = "Click me!";
_button.Click += new EventHandler(this.ButtonClickHandler);
this.Controls.Add(_button);
}
private void ButtonClickHandler(object sender, EventArgs e)
{
_label.Text = _textBox.Text;
}
}
}

VB.NET


Imports System
Imports System.Collections.Specialized
Imports System.Text
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Namespace SimpleComposite
Public Class MyCompositeControl
Inherits CompositeControl
Private _textBox As TextBox
Private _label As Label
Private _button As Button
Protected Overrides Sub CreateChildControls()
_textBox = New TextBox()
_textBox.ID = "MyTextBox"
Me.Controls.Add(_textBox)
_label = New Label()
_label.ID = "MyLabel"
Me.Controls.Add(_label)
_button = New Button()
_button.ID = "MyButton"
_button.Text = "Click me!"
_button.Click += New EventHandler(Me.ButtonClickHandler)
Me.Controls.Add(_button)
End Sub
Private Sub ButtonClickHandler(sender As Object, e As EventArgs)
_label.Text = _textBox.Text
End Sub
End Class
End Namespace

.aspx page


<%@ Page Language="C#" Codefile="Default.aspx.cs" Inherits="Default_aspx" %>
<%@ Register Assembly="SimpleComposite" Namespace="SimpleComposite" TagPrefix="Sample" %>
<html>
<body>
<form id="form1" runat="server">
<Sample:MyCompositeControl ID="CompositeTest" Runat="Server" />
</form>
</body>
</html>

Figure 9.3. Our composite control rendered in the browser

Could it be any easier? The CreateChildControls() method creates the controls one by one, assigning values to some of their properties and then adding them to the control collection. The button control gets one extra step, where we add an event handler to its Click method. The syntax for this is the same as what we used in Chapter 8, "HttpHandlers and HttpModules," for our sample HttpModule.

The event handler itself, which we're calling ButtonClick Handler(), has the familiar parameters of every other event handler: an object and an EventArgs object. When we type "Hello!" in the text box and click the button, it fires off our event handler and copies the value in the text box to the label.

Of course, you can see in Figure 9.3 that the formatting of our composite control leaves a lot to be desired. The controls are rendered in the order that they were added to the collection. There's something we can do about this, of course, and if you guessed that it involves overriding the Render() method of the base class, you were right!

As with our custom server control, we'll override Render() and create our own implementation. To write one of our controls, we call its RenderControl() method and pass in the HtmlTextWriter parameter of the Render() method. This might feel a little backward because in our custom control we were calling methods of the HtmlTextWriter.

This act of overriding Render() enables us to render the controls in the order that we'd like, but we also need to generate some HTML in between them to format them nicely. Fortunately, the HtmlTextWriter has a number of methods that enable us to cleanly create a tree of XHTML- compliant tags. There's also an enumeration called HtmlTextWriterTag that enables us to pass in values to the writer that correspond to common HTML elements. The result of this, our overridden Render() method, is shown in Listing 9.11. The listing also shows the HTML rendered and sent to the browser. Figure 9.4 shows the display in the browser.

Listing 9.11. The Render() method and the HTML rendered for the browser

C#


protected override void Render(HtmlTextWriter writer)
{
writer.RenderBeginTag(HtmlTextWriterTag.Table);
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
_textBox.RenderControl(writer);
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
_button.RenderControl(writer);
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
_label.RenderControl(writer);
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderEndTag();
}

VB.NET


Protected Overrides Sub Render(writer As HtmlTextWriter)
writer.RenderBeginTag(HtmlTextWriterTag.Table)
writer.RenderBeginTag(HtmlTextWriterTag.Tr)
writer.RenderBeginTag(HtmlTextWriterTag.Td)
_textBox.RenderControl(writer)
writer.RenderEndTag()
writer.RenderEndTag()
writer.RenderBeginTag(HtmlTextWriterTag.Tr)
writer.RenderBeginTag(HtmlTextWriterTag.Td)
_button.RenderControl(writer)
writer.RenderEndTag()
writer.RenderEndTag()
writer.RenderBeginTag(HtmlTextWriterTag.Tr)
writer.RenderBeginTag(HtmlTextWriterTag.Td)
_label.RenderControl(writer)
writer.RenderEndTag()
writer.RenderEndTag()
writer.RenderEndTag()
End Sub

HTML source sent to browser

[View full width]


<table>
<tr>
<td><input name="CompositeTest$MyTextBox" type="text" value="Hello!"
id="CompositeTest_MyTextBox" /></td>
</tr><tr>
<td><input type="submit" name="CompositeTest$MyButton" value="Click me!"
id="CompositeTest_MyButton" /></td>
</tr><tr>
<td><span id="CompositeTest_MyLabel">Hello!</span></td>
</tr>
</table>

Figure 9.4. Our formatted composite control as seen in the browser

The methods used should be straightforward. We build a tree of tags, starting with a table tag by calling the HtmlTextWriter's Render BeginTag() method. We do the same for table row and cell, and then we finally render our TextBox as we described. To close the last tag we opened, we simply call the RenderEndTag() method. We don't need to pass in any parameters because this method knows to close the last tag that hasn't yet been closed.


If you need to work with XML, similar methods are found in the XmlTextWriter class, except that they're called WriteStartElement() and WriteEndElement(). They make the creation of well-formed XML a breeze.

Although our composite control does some fabulous things as a self-contained unit, it doesn't have any means to communicate with your own code. As with our custom server control example, you can add properties and events to give your calling code something to interact with. One advantage of the composite control is that each individual control already has an array of events and event handlers for you to interact with, so you don't have to write your own for each component of the user interface.


You might be wondering why we marked our methods "protected." Recall from Chapter 2, "Classes: The Code Behind the Objects," that a protected member can only be called from within the class or from within the derived class. If someone were to derive from our class to make their own implementation, we don't want users of the derived control calling the member of the base class (our class) because it would cause confusion between the original member and the derived member. Therefore, we "protect" the original version.


/ 146