ast issue I gave you a 'hit-the-ground-running' introduction to custom Web control development and showed you how to build a rendered control and an inherited control.
In this issue you'll complete your inherited control by adding styling, sizing capabilities, as well as instruct it how to raise events. Afterward you will jump into building the last control of the series, the EmailContact control, bringing together the previous two controls with some business functionality into a powerful composite Web control.
In the first part of this article
you learned how to create an inherited Web control, as well as a fairly functional rendered Web control. In this part you'll learn three professional touches for your custom Web control. First, you'll learn how to make all parts of your custom control resize correctly. Next, you'll learn how to capture an event when the button is clicked or when text in the textbox changes. Finally, you'll learn how to add basic styling.
When you drop any Web control on a form, you're probably used to sizing it by dragging one of its sizing points in whatever direction you want. The problem here is that the Web control you're building consists of three HTML elements, and you want to be able to size each one individually to give the FormField control maximum usefulness. The built-in Width
properties that the control has comes from the Control class that you are ultimately inheriting from, and it corresponds to the control as a whole. If you try to resize the control using these properties as it currently stands, nothing happens. This is because you have not added sizing attributes to the contained elements, so they stay exactly as-is. I'm going to do something later with these existing properties, but for now I want you to add two properties called CaptionWidth
. For the purposes of this article, I'm only going to show you how to deal with widths, but the downloadable code contains code to handle heights as well. I left out a Width
property for the textbox for a reason, as I'll explain later.
A property that handles height or width for an element is of type Unit. Here's the code for the CaptionWidth
Public Property CaptionWidth() As Unit
If CType( _
ViewState("CaptionWidth"), Object) _
Is Nothing Then
Return CType( _
Set(ByVal Value As Unit)
ViewState("CaptionWidth") = Value
public Unit CaptionWidth
ViewState["CaptionWidth"]) == null)
ViewState["CaptionWidth"] = value;
As you can see, the same ViewState-oriented property technique is used here as described earlier in the article. The Unit object is serializable so it can be fully persisted in the ViewState variable. Now that you've added the new properties, you need to do something with them. Remember that earlier I taught you that you can use the AddAttribute
method of the HtmlTextWriter object to add tag attributes to the upcoming RenderBeginTag
call. That's exactly how you're going to set the Width
attribute to the "span" tag and "input" tag for the button, with one minor difference I'll explain in a minute.
And of course, you would have a similar line for the ButtonWidth
property. Now you can set these properties individually to adjust the width of the caption and the button. As you realized, there's one element of the Web control whose width I have not handled this way. In fact, there's a reason I haven't yet showed you how to handle this element. To make the control more programmer-friendly, I'm letting the textbox take the remaining width of the entire control; that is the total width of the Web control minus the width of the caption and the button (and don't forget those two spaces you inserted between elements-calculated to be 10 pixels). The value that you're going to use to set the width of the textbox will consist of the total width of the control (the Width
property) minus the value of CaptionWidth
, minus the value of ButtonWidth
, and minus 10. The subtraction of the ButtonWidth
value will depend on the setting of the ButtonVisible
property and the number 10 accounts for the extra spaces rendered between the elements. I derived the number 10 by trial and error to see what looked best in the designer. You'll use the calculated value to set the Width attribute of the textbox's "input" tag.
Dim i_Width As Integer = _
CType(Me.Width.Value, Integer) -
(CType(Me.CaptionWidth.Value, Integer) - 10)
If Me.ButtonVisible Then
i_Width -= CType( _
If i_Width < 20 Then i_Width = 20
int i_Width = ((int)(this.Width.Value)) -
((int)(this.CaptionWidth.Value) - 10);
i_Width -= ((int)(this.ButtonWidth.Value));
if (i_Width < 20)
i_Width = 20;
|Figure 1. The FormField Control: The figure shows the FormField control in action.|
Notice that you're also ensuring a minimum total width of 20 for the control. In the downloadable code for the finished FormField control (Figure 1
), I also handle the Width
property to account for percentages as well as pixel entry as its value. This will become necessary when I get to the composite control later, but for now I'm not going to worry about it. Another thing to note is that you're using a different method from the AddAttribute
you used before. The AddStyleAttribute
takes care of adding the property, not as an attribute to the tag, but as an attribute within the HTML style attribute. Later when I address styling, I'll touch on this some more.
If you try sizing this control on a Web Form now, you will see that the textbox stretches to the size of the entire control while leaving the caption and button the same width. Those elements will only be sized by setting their properties individually. Now that you can size the control properly, you're going to add some actual functionality for handling postbacks and handling events.