Properties

Custom controls can expose properties just as any other class can. You access these properties either programmatically (e.g., in code-behind) or declaratively, by setting attributes of the custom control, as you did in the text page, and as shown here:

<OReilly:WebCustomControl1 Runat="Server" Text="Hello World!" />

The Text property of the control is accessed through the Text attribute in the web page.

In the case of the Text property and the Text attribute, the mapping between the attribute and the underlying property is straightforward because both are strings. ASP.NET will provide intelligent conversion of other types, however. For example, if the underlying type is an integer or a long, the attribute will be converted to the appropriate value type. If the value is an enumeration, ASP.NET matches the string value against the evaluation name and sets the correct enumeration value. If the value is a Boolean, ASP.NET matches the string value against the Boolean value; that is, it will match the string "True" to the Boolean value true.

The Render method

The key method of the custom control is Render. This method is declared in the base class, and must be overridden in your derived class if you wish to take control of rendering to the page. In Examples 14-8 and 14-9, the Render method uses the HtmlTextWriter object passed in as a parameter to write the string held in the Text property.

The HtmlTextWriter class derives from TextWriter and provides rich formatting capabilities. HtmlTextWriter will ensure that the elements produced are well-formed, and it will manage the attributes, including style attributes. Thus, if you want to set the text to red, you can add a color attribute, passing in an enumerated color object that you've translated to HTML, as shown here:

output.AddStyleAttribute("color", ColorTranslator.ToHtml(Color.Red));

You can set the text to be within header (<h2>) tags with the HtmlTextWriter's RenderBeginTag and RenderEndTag methods:

The result is that when the text is output, the correct tags are created, as shown in Figure 14-12. (The source output that illustrates the HTML rendered by the HtmlTextWriter is circled and highlighted.)

Figure 14-12.The output and its source

Maintaining state

In the next example, you'll add a button to increase the size of the text. To accomplish this, you'll eschew the rendering support of the HtmlTextWriter, instead writing the text yourself, using a new Size property (to set the size of the output text). The C# code for the Render method should appear as follows:

The Size property must maintain its state through the postback fired by pressing the button. This is as simple as writing to and reading from the ViewState collection maintained by the page (see Chapter 6), as shown in the C# property definition of the Size property:

Public Property Size( ) As Integer
Get
Return Convert.ToInt32(ViewState("Size"))
End Get
Set(ByVal Value As Integer)
ViewState("Size") = Value.ToString( )
End Set
End Property

The property Get method retrieves the value from ViewState, casts it to a string in the case of C#, and then converts that string to its integer equivalent. The property Set method stashes a string representing the size into ViewState.

To ensure that a valid value is in ViewState to start with, you'll also add a constructor to this control. In C#, the constructor is:

public WebCustomControl1( )
{
ViewState["Size"] = "1";
}

In VB.NET, it is:

Public Sub New( )
ViewState("Size") = "1"
End Sub

The constructor initializes the value held in ViewState to 1. Each press of the button will update the Size property. To make this work, you'll add a button declaration in the test page:

The important changes here are that you've added an ID attribute (Button1) and defined an event handler for the button. You will also need to create an event handler in the code-behind page.

Be sure to add a reference to the CustomControls DLL file to the web page. That will allow Intellisense to see your object, and you'll be able to declare the control in the code-behind page. In C#, this takes the form: