Custom Web Controls Demystified, Part 1

hen ASP.NET was released in 2002, it gave Web developers a whole new design paradigm to work with; one that varied greatly from the classic Active Server Pages (ASP) that many Web developers had worked with in the past.

At the heart of this new way of developing Web applications are components known as Web controls. Though most Web developers use them while developing ASP.NET applications, many have not yet dived into the world of creating their own custom Web controls, even after all this time?yet all .NET developers will soon face another release of .NET. In this article, I will attempt to give you a head-to-toe understanding of how Web controls work, and how to create them for yourself.

As a freelance consultant, I’ve noticed that when receiving ASP.NET skill-set requirements from clients or recruiters for contract jobs, knowledge of how to program custom Web controls is never requested. Now, I don’t expect my business customers to know specific technologies when requesting a solution to their problems, but even IT departments in charge of screening consultants for required skills, and that request experience in developing reusable software seem to lack knowledge of this powerful part of ASP.NET. Programming Web controls goes way beyond using the ones that come with Visual Studio and can greatly change the way you develop and reuse code in Web applications.

Web controls give ASP.NET developers the same advantages of reusability, encapsulation, and complete OOP that Windows Form developers have had for a while.

I recently published an article on Declarative Programming using Web controls, where I generalized an approach to ASP.NET development using custom Web controls. This time, we’re going to travel backwards and learn exactly how these extremely reusable components work, and how we can create our own to bring a level of object-oriented development to the UI level that was not easily achievable in the past. We will be developing three useful custom Web controls in this article that will cover many, though not all, of the technologies available to us. At the end, you will hopefully walk away with not only a good understanding of how to develop custom Web controls, but also three very useful Web controls that you can use as-is or as educational tools to get you going in developing more, on you own, and take advantage of this powerful yet underused part of the .NET world.

The “What” and the “How”
Put simply, ASP.NET Web controls are server-processed components that render standard HTML to a browser. Even in today’s highly evolved world of Web application development, HTML is still all our browsers really understand. Sure, there’s JavaScript, embedded OCXs, Flash animations, and so on, but all of them are kicked off by some kind of HTML.

When Visual Basic 5 introduced the Control Creation Edition, or CCE, Windows programmers were first given the opportunity to develop reusable OCXs (later to become ActiveX controls) of their own. For me at least, this changed the way I developed Windows applications. ASP.NET Web controls give ASP.NET developers the same advantages in reusability, encapsulation, and now complete object-orientation, when developing Web applications. However, the visual aspect of Windows Form controls and Web controls to a developer using them on a Windows form or a Web Form is where the similarity ends.

You can essentially think of Web controls as code-generators. They are components that, through simple or complex logic, generate standard HTML that will get rendered in a browser. The functionality behind Web controls that generates the appropriate HTML gets processed within the ASP.NET page lifecycle. From a code standpoint, Web controls are just classes with methods, properties, and events?just like any other class you have been programming with for over three years. This class-like nature gives developers the power of object-oriented programming at the UI level where they did not really have it before.

What You Need
This article assumes general .NET Framework skills, knowledge of programming ASP.NET applications, and object-oriented design. I also assume the reader understands key concepts in .NET development such as “decorating with Attributes” and “importing Namespaces,” etc. Custom Web control development is a huge topic and the subject of complete books. I will provide as detailed and complete a tutorial as possible during the development of sample Web controls in the attempt to whet your appetite to pursue more knowledge on the subject.

Advantages of Using Web Controls
Programming with custom Web controls provides several advantages in all stages of development, among which are:

  • Isolation of Visual Components. Web controls allow you to group related visual components together into a single component and encapsulate all functionality and visual representation associated with that component within the Web control. This is especially true in the case of Composite Web controls, but more on that later.
  • Reusability, Reusability, Reusability. Writing custom Web controls for your applications will provide you with the ultimate method of reusability in Web development. Web controls compile to an assembly, just like any other Web component; so you can reuse them on any page of any Web application you want, depending, of course, on the desired intention of the specific Web control.
  • Cross-Browser Compatibility. In the old days, developers performed browser-checks on a Web page, whether it was in ASP script code or client-side Jscript. Using the results of this browser check, you could decide how to render different HTML for the appropriate browser your application was being accessed from. When you develop a custom Web control, you can perform your browser checks within the control’s code itself; letting the Web control decide how it should properly render itself.
  • Self-Maintaining State. Web controls can, and usually do, control their own state in order to persist information they need during page postbacks.
  • Full Object-Orientation. As I mentioned before, Web controls are just classes, albeit pretty elaborate ones. This means they can inherit, be inherited, implement interfaces, and take part in any design pattern you see appropriate to use.
  • Declarative Programming. Web controls allow you to program declaratively. This means they let you separate the “What to do” from the “How it is done” on your Web Forms. They help you eliminate clutter on your Web Forms by removing code and placing it with the Web controls, making the code on your Web Form much easier to follow. I’ll talk a little more about this at the end of the article but if you want more detail on Declarative Programming, check out my article titled, “ASP.NET Development Through Web Controls and Declarative Programming” in the March/April 2005 issue of CoDe Magazine. Like it or not, things are moving more and more toward Declarative Programming with the coming of XAML in the near future.
  • Did I Mention Reusability? I can’t stress enough, the level of reusability that custom Web controls bring to the world of Web development.

Types of Web Controls
There are three types of Web controls, each with their own characteristics and advantages. When to use one or another is a topic of discussion on several forums. The problem is that some discussions seem to favor one type while other forums favor another, and both for the same type of use. I am going to explain each type and also give you my own opinion, coming from my experience, as to when each type is useful.

Inherited Controls
Inherited controls consist of a class that inherits from an existing Web control class, usually one of the ones provided by Visual Studio. You usually use this type of custom Web control when you simply need to extend an already existing control with some extra functionality. For example, you might have a dropdown box that pre-fills itself with information. Say you anticipate many places within a site (or multiple sites for that matter) where you need the ability to select a US state. There’s no need to use a standard dropdown control and then fill each one in each of the page’s code-behind class. Simply write a class that inherits from the existing dropdown control class, add the functionality to fill itself with US states, and that’s it. Dropping that control on a Web Form will automatically render it with the US states pre-filled.

As another example, consider a textbox with some added properties. These can include a Required property which the page can check during validation stages, or a ConvertCase property that can convert the case of the text to either all upper or all lower when focus leaves the control. Yet another example of a useful inherited control can be a button that contains an extra property called ConfirmationMessage. Setting this property to something other than an empty string can pop up a confirmation dialog when the button is clicked. Later in this article, I’ll show you how to develop this custom button control.

Rendered Controls
This type of custom Web control gets its name because it directly renders HTML straight through the rendering engine. The control typically doesn’t contain any other controls, thus focusing all its power and speed towards rendering the HTML that will ultimately decide how the output of the control looks on a Web page. Rendered controls work by overriding certain methods of its base that will control the fine-grained rendering of HTML tags and attributes. These controls can handle page postbacks by implementing some interfaces which give them the ability to raise events and/or check data values during that action. Because everything is controlled at a fine-grain level, there can typically be a bit more work involved when developing complex rendered controls. The proper naming, styling, and event handling of a rendered control’s contained HTML elements must all be handled through an extensive amount of code. I’ll talk about the advantages and disadvantages of this type of Web control after I describe composite controls.

Composite Controls
A composite Web control is a control that contains one or more other Web controls. This control relies on the rendering ability of the Web controls it contains, acting as a container mechanism, deciding where to place said controls by providing framing HTML code around them. This will make a lot more sense when I show you how to develop one later. Because composite controls instantiate one or more (possibly many) child controls, the general consensus is that they can become a little heavy as far as rendering performance is concerned. Now, before you let such a negative statement sink in too deeply, let me share from personal experience what I consider the advantages and disadvantages of composite controls vs. rendered controls, as well as when each should be used.

I acknowledge the fact that rendered controls certainly do render faster than composite controls. This is because they are writing HTML directly through the rendering engine. At the same time, I feel composite controls are more straightforward to develop. If you know how to use the Web controls that Visual Studio provides for you then you’re halfway there in developing composite Web controls. In defense of composite Web controls and their slower rendering, if you’re developing a Web Form and place several Label and Textbox Web controls on it, you are going to take a performance hit similar to rendering one Web control that contains a similar set of Labels and Textboxes.

This leads me to how I make my decision as to what type of Web control I am going to write. If the control I need to develop is one in which I’ll use a lot of instances on a page, I typically use a rendered control approach. If I am developing a control that will have a more complex UI and will typically be used once or twice, maybe even three times on a Web page, then I choose a Composite control. I haven’t forgotten about the first type I described, the inherited control. I use these for controls such as those described in the examples I named when I explained the control to you. They are typically simple extensions of already existing controls. Notice I said “simple extensions” not “extensions of simple controls.” You can inherit a very complex composite control and provide further functionality for it in the extended class.

As far as performance is concerned, you also need to take into consideration the target sites for your control. Internet sites usually are bit more performance-conscience than Intranet sites. You can certainly write any composite control as a rendered control, though it will probably take more time and a lot more code. This is where the other “performance” comes into play your performance as a developer and the time constraints you may have upon you. I use composite controls as the “Declarative” approach to my ASP.NET development, breaking down my sites into smaller, more manageable components which consist of you guessed it, Web controls.

Let’s Code Already!
I’m going to show you how to develop three Web controls in the rest of this article. I will go into as much detail as I can considering that this is an article and not a book. Some of the things I will cover will be more general than others and I’m hoping that you get intrigued enough to read further on the subject from the books I’ve listed in the sidebar called Good Books for Learning How to Develop Custom ASP.NET Controls.”

The first custom Web control you’ll learn to develop is a button that will have the ability to pop up a confirmation dialog when it is clicked. This will give the user the ability to cancel whatever processing would have taken place when the button was clicked. I’ll show you how to develop this Web control as an inherited control that I’ll call the ConfirmationButton.

Next you’ll learn to develop a second custom Web control I’ll call the FormField control. This control was in my article on Declarative Programming. This control is a combination of a label, a textbox, and a button that you can arrange in a variety of ways. The idea behind this control is that it serves as the basis for data entry on a Web page. Because of the heavy use this control may receive on a single Web page, I’ll develop this as a rendered control.

The third and last custom Web control that you’ll lean to develop is an EmailContact control. You no doubt have seen many Web sites that provide the user with a “Contact Us” page. This page usually includes a small form that allows the visitor of the site to send an e-mail to the site’s Webmaster. You can see similar forms in today’s most popular type of Web site among the develop community?the blog. You may see this kind of form when you leave feedback for a blog posting. I’ll show you how to encapsulate everything necessary to build this kind of form into a custom Web control. You’ll even see how to build the actual e-mailing functionality directly into the control. I’ll show you how to develop this control as a composite control and will contain within it both the FormField rendered control and the ConfirmationButton inherited control.

The WebControl class inherits form the Control class and adds some styling properties to it.

You will enable all these controls with certain functionality during the development steps in this article. At the end of this article, I will list additional functionality that the final versions of the controls include in the downloadable code.

So let’s get to work…

The ConfirmationButton Control
The first custom Web control will also be the simplest. The ConfirmationButton control will be a simple class that starts by inheriting from the built-in Button Web control that ships with Visual Studio.

In VB.NET:

   Public Class ConfirmationButton       Inherits Button   End Class

In C#:

   public class ConfirmationButton : Button   {   }

The parent Button class of this control resides in the System.Web.UI.WebControls namespace, which you obtain by referencing the System.Web.dll in your project. If this class is compiled as-is, it will duplicate the functionality of the Button class that .NET provides. In fact, you can compile this class, add it to the toolbox for a Web Form, then drop it on a Web Form and it will be no different than dropping a Button control from the Web Form toolbox.

Properties
You will make only two simple changes to your new class. The first is the addition of a property. I want to describe this process in detail, however, because this is the way you’ll add most properties in all three controls you’ll build in this article. I say most properties because when you build the composite control, you’ll code “mapped” properties a bit differently, but I’ll get to that later. You want to add a ConfirmationMessage property to your ConfirmationButton class, and a value other than an empty string will indicate that you want a confirmation dialog box to pop up when a user clicks a button. Here is the code for your new property.

In VB.NET:

   Public Property ConfirmationMessage() As String      Get         If CType( _            VieState("ConfirmationMessage"), _            Object) Is Nothing Then            Return String.Empty         End If         Return CType( _            ViewState("ConfirmationMessage"), String)      End Get      Set(ByVal Value As String)         ViewState("ConfirmationMessage") = Value      End Set   End Property

In C#:

   public string ConfirmationMessage   {      get      {         if((object)            ViewState["ConfirmationMessage"] ==            null) return String.Empty;         return (string)             ViewState["ConfirmationMessage"];      }      set      {         ViewState["ConfirmationMessage"] = value;      }   }

Look closely and you’ll notice that this property is not much different than properties you write every day in your classes. The typical procedure for a property is to expose a member variable of some kind. You’ve no doubt done this time and time again. The ConfirmationMessage property works similarly with the difference being that you aren’t using a privately declared member variable. Instead, you’re using a ViewState variable as the internal storage for the ConfirmationMessage property; so let me talk a little more about this.

The get accessor in the property returns the value of the internal variable. In the property, this is stored in ViewState[“ConfirmationMessage”], and the set accessor sets the ViewState variable to whatever you set the property to. ViewState is a variable of type StateBag. Like the famous Session variables and Cookie variables that you have used in Web applications, it is a dictionary that contains one or more values accessed by a key. In this case, I’ve standardized the naming conventions so the key is equivalent to the name of the property. Keep this in mind because you’re going to see it a lot more through the rest of this article. The contents of the ViewState variable are stored in the __ViewState hidden field on your Web page in an encrypted format and are used to save and retrieve values that you need to persist in between page postbacks. The rest of the code around the ‘return’ statement in the get accessor checks to see if the specific ViewState value exists in the ViewState array. Because ViewState is a dictionary type (actually, StateBag is), checking for an entry in it that does not exist does not raise an exception; instead, it adds an empty object. The if statement checks the ViewState value for Nothing (or null). If this is the case, then it will return whatever you want the default value to be. The check for Nothing (or null) is done with an object-cast of the ViewState variable. The reason for this is due to the nature of the StateBag object, where an attempted access of a non-existing value automatically adds a null value.

Standard Attributes
You’ll also have a few additions for this property that will be “standard operating procedure” for all properties you write in custom Web controls. These consist of certain attributes with which you’ll decorate your property. Some properties will receive more attribute decorations than others, but all will receive at least four attributes: Category, Description, Bindable, and DefaultValue. All are found in the System.ComponentModel namespace.

In VB.NET:

   < _      Category("Behavior"), _      Description("Gets or sets the message to be " & _       "displayed in a confirmation dialog. The " & _      "dialog will present itself if this property " & _      "is not empty."), _      DefaultValue(""), _      Bindable(True) _   > _

In C#:

   [   Category("Behavior"),   Description(""),   DefaultValue(""),   Bindable(true)   ]

Category Attribute
This attribute specifies the category that your property will be listed under when you view it in the property browser. Indulge me in a comical tangent: Make sure you do not accidentally misspell the category name. I can’t tell you how many times I have misspelled the word “Appearance” when using it as a Category. Instead, I’ve typed “Apperance” and guess what the property browser shows? That’s right?two categories, “Appearance” and “Apperance.”

Description Attribute
This attribute determines the description of the property that is displayed at the bottom of the property browser. It provides simple instructions for programmers using your Web control.

DefaultValue Attribute
Contrary to what the name of this attribute makes you assume, it does not determine what gets stored in the property by default. As you saw when I described the Property statement, you’re setting the default value for the ViewState variable in your get accessor. This attribute lets Visual Studio know what the default value of the property will be for two main reasons. The first is that it lets the property browser know whether to display the value of the property in bold letters or not. If you haven’t noticed before, when you drop a control on a Web Form and refer to the property browser, all the property values are displayed in normal font until you change their values, after which they are displayed in bold letters. This lets you know that the entered value is not the default value for the property. The second reason is that only properties with non-default values appear in the ASPX tags that define your Web control on a Web Form.

Bindable Attribute
This attribute determines if the property will participate in data binding functionality. The data source for the property can be defined in an expression. This topic is beyond the scope of this article, but if you want further information, look at the Data category of a typical Web control in the property browser and click on the DataBindings value, then click the Help button for a full explanation.

This is the technique for creating properties that you’ll see in many of the properties going forward in all your Web controls, so this will be the only place where I will get into a lot of detail for Web control properties.

Rendering the Control
Now that you’ve added your custom property to the Web control, you need to tell the control what to do with it. Remember that your goal is to check the content of this property and if it is anything but an empty string, you want a confirmation dialog to pop up and let the user confirm or cancel the postback that the button initiates. When you create custom Web controls, it’s important to understand what you want the eventual HTML result to be. Remember, I stated earlier that Web controls are essentially code generators that render standard HTML. The ConfirmationButton control, like its Button base class, renders a standard HTML input tag that looks something like this.

   

The rest of the tag is not important at this time. What is important is what you would need to add to such an HTML tag if you wanted a confirmation pop up?and that is some Jscript code in its onclick event, such as:

   

This Jscript code will simply pop up a confirmation message asking “Are you sure?” Then, if the user clicks Cancel, the code returns a value of false. This has the effect of canceling the submission of the form originally intended by pressing the button, and effectively canceling the postback. Now you need to get this code into your Web control. You do this by overriding the AddAttributestoRender method. This method adds tag attributes to the rendered HTML tag your control will eventually produce.

In VB.NET:

   Protected Overrides Sub AddAttributesToRender( _      ByVal writer As HtmlTextWriter)      If Me.ConfirmationMessage <> _         String.Empty Then         writer.AddAttribute( _            HtmlTextWriterAttribute. _            Onclick, "if(!confirm('" & _            Me.ConfirmationMessage.Replace( _            "'", "'") + "')) return false;")      End If      MyBase.AddAttributesToRender(writer)   End Sub

In C#:

   protected override void AddAttributesToRender(      HtmlTextWriter writer)       {      if (this.ConfirmationMessage != String.Empty)      {         writer.AddAttribute(            HtmlTextWriterAttribute.Onclick,            "if(!confirm('" +             this.ConfirmationMessage.Replace("'", "'") +             "')) return false;");       }      base.AddAttributesToRender(writer);   }

The argument of type HtmlTextWriter is used to write to the HTML rendering engine. You will see much code like this later. One of the methods of this type allows you to add an attribute to the HTML tag that will later get rendered. As you can see, you’re adding an onclick attribute and providing the appropriate Jscript to perform the task. The code uses the Replace statement to replace any single ticks with ones preceded by a backslash. This is standard Jscript syntax.

I’ve twice mentioned the tag that is rendered. The Button class code has decided this for you so it is not discussed in detail here. You’re taking it on faith that Microsoft’s Button control renders an tag.

That’s it for the ConfirmationButton class. If you compile it you can add it to your toolbox and use it on a Web Form. When you drag it onto a Web Form and examine the property browser, you’ll notice the ConfirmationMessage property under the Behavior category. Set this property to a value of “Are you sure?”, run the Web Form and press the button, and you should see something like Figure 1.

?
Figure 1: Confirmation Message: The figure shows the message that appears when a user presses the ConfirmationButton.

If you click “Yes,” you should see the page postback as usual, but clicking “No” will simply make the popup window disappear and you’ll notice that the postback will be cancelled. (You can tell if the postback occurs by looking at the bottom status bar of the browser.)

With very little work, you could have your button decide whether or not to use the ConfirmationMessage property based on another Boolean property called Confirm; instead of depending on the existence of the message text.

The assembly, or DLL file, that this class compiled into can be distributed to any Web applications and used freely. This is where the extreme reusability factor of custom Web controls comes in. In fact, once this control exists in your toolbox, dragging it onto a Web Form will automatically add the reference to its DLL to your ASP.NET application.

Before I wrap this up, I want to touch on one other thing that will apply to all Web controls. I’m referring to the control’s tag prefix. All of you have used the Visual Studio Web controls already, and I’m sure you’ve noticed the ASPX code that gets generated when you drag something like a textbox onto a Web Form.

   

The “asp:” in this case is called the tag prefix. By default, .NET uses “cc1” for your new control but you’re going to change it to something else. Since my company name is InfoTek Consulting Group, I tend to use “icg” as the tag prefix for all of my Web controls. I’ll place the definition for a tag prefix in the AssemblyInfo file. The declaration looks like this.

   [assembly: TagPrefix("InfoTek.Web.UI.WebControls",      "icg")]

For VB.NET projects, replace the square brackets ([])with angle brackets (< and >). The first argument specifies the custom control’s namespace and the second argument specifies the tag prefix you want to use. By adding this attribute to the AssemblyInfo file, your ConfirmationButton control takes this form.

   

Congratulations. You’ve just developed a very simple, yet useful inherited Web control. You can use the technique I showed you here on any type control and it is only limited by your own creativity. For practice, try creating another inherited control but make it extend a Textbox control to convert its contents to upper or lower case when it loses focus. Here’s a hint: the Jscript onblur event gets fired when the control loses focus. I’ll leave the rest to you.

The FormField Control
I’ll use the FormField control as an example of a rendered custom Web control. You’ll find this control to be extremely useful in any Web application and you’d very likely use it heavily within a single page. As I explained before, it is for that reason that I’ve chosen to develop this control as a rendered Web control, which is one that directly writes to the HTML rendering engine; making the control very efficient. This control will serve well in any Web Form (or other Web controls) where data-entry is performed. The control replaces the need to drop a separate label, textbox, and sometimes a button on Web Forms several times support fields used for data-entry. The label and textbox are common everywhere, but the button is an added extra for this control. The control can display a button to the left of the textbox. This button will raise an event to the code-behind that can be trapped by whatever page uses the control. This feature, along with some interesting properties that we’ll go over soon, will give the FormField control some really cool functionality. Figure 2 shows what the finished control will look like in a standard layout.

?
Figure 2: The FormField control in a finished stage.

Now you can start to create the class that will become your FormField control. This class will inherit from the System.Web.UI.WebControls.WebControl class, one of two classes that [non-inherited] custom Web controls inherit from. The other is the Control class but it does not provide the styling properties that you want for your control.

In VB.NET:

   Public Class FormField      Inherits WebControl   End Class

In C#:

   public class FormField : WebControl   {   }

I’ll discuss styling later but for now your next step is to add some properties to your control.

Properties
In the interest of space, I will not go into the property details here but the final downloadable code has every property fully documented, specifying the category they fall into and their description, provided to each property via the attributes discussed earlier. The properties that you’ll add to this control will determine how the control renders its contents and what kind of behavior it provides to the Web Form using it. At the end of this section, I’ll give you a quick list of functionality the final control has. Details on all of this is just too much for this article, but I will tell you that in the process of adding functionality to this and the control that follows, I’ll demonstrate a variety of features you can give your Web controls. This should give you a good reference to use when building more controls in the future. Table 1 lists three properties that I’ll refer to during the development that follows.

Table 1: These three properties are among many used in the FormField control.

Property

Type

Default

Description

Caption

string

Form Field:

This property gets or sets the caption text that will display in the FormField control.

ButtonCaption

string

This property gets or sets the caption for the button that will display in the FormField control.

Text

string

{nothing}

Like it’s counterpart in the standard Textbox control, this property gets or sets the value that gets entered or displayed in the textbox that will be part of the FormField control.

Since this is going to be a rendered control, the next step is to jump right into the method that provides the rendering engine that you’ll write to.

Rendering
The Render method, which you need to override, has only one argument of the type System.Web.UI.HtmlTextWriter. This argument, which you’ll call output, is the entry point into the Html rendering engine. To write HTML (or any other) text using this object, you could use this snippet.

   output.write("");

This code would write out the text between the quotes directly without any other process in between. This kind of direct access makes rendered controls very efficient for rendering speed. While your control will write output using this object, your control won’t write literal text as shown in the code snippet above. Instead, the HtmlTextWriter object provides many methods that help you create valid HTML, so you’ll take advantage of that.

Speaking of HTML, now’s a good time to describe what kind of HTML you want to render for the FormField control. Remember the FormField control will be made up of three parts: a caption, a textbox, and a button. Essentially, the HTML will give the control a tag, an tag, and an tag. I’ll walk you through that and then we’ll build upon it. Listing 1 shows the VB .NET code that will render the HTML for the three sections of your custom control in its simplest form. Listing 2 shows the same process in C#.

Here’s a piece of HTML that will help you analyze this code:

   Enter Name:

This is essentially the piece of code that the first five code lines of the Render method create. You want the label to use the “span” tag for the caption of the FormField control. This basic HTML tag contains literal text and can apply any styling you desire to that text.

Note that the third, fourth, and fifth lines in the code in the listing uses the RenderBeginTag method of the HtmlTextWriter object to render a “span” tag. Then it renders the caption text from the Caption property, and closes the tag using the RenderEndTag method. You don’t need to specify which tag need to close because the rendering engine keeps track for you automatically. The first two lines in the code use the HtmlTextWriter.AddAttribute method to add custom attributes that will get rendered with the “span” tag.

In the sample HTML above, the “span” tag contains id and name attributes. You add these attributes using the AddAttribute method in conjunction with an HtmlTextWriterAttribute enum value. Every call to AddAttribute gets “stacked” and the attributes all get added to whatever is the next tag rendered with RenderBeginTag. That clears the attribute stack and the task starts again. You can see this demonstrated in the listing code where the id and name attributes get added to the three tags being rendered, leading this article to an important topic for naming rendered controls.

Naming Controls
When a programmer drops your newly created FormField control on a Web Form, the first thing they usually do is give it a name, such as fldName. The rendered control, however, is made up of several HTML tags that would normally each have their own identifiers. Since you are manually rendering the entire HTML composing your custom Web control, it’s obviously up to you to provide those HTML tags with appropriate identifiers. My code examples will follow the ASP.NET naming convention that all out-of-the-box Web controls use. The two attributes you must provide for each HTML tag are id and name. The attribute values should be the name of the encapsulating control (which is your Web control) followed by whatever name you want.

It goes without saying that this name should make sense if you read the rendered HTML from the browser. The delimiter between the two should be a colon (:) for the name attribute and an underscore (_) for the id attribute. You have no way of knowing what a developer will name your control when you use the UniqueID property of the Control class, which is ultimately the class your control inherits from. Following this naming convention, you want to keep the code easy for any programmer to understand and allow your custom Web controls to maintain the same standards that Microsoft and other control vendors use.

Note in the code that the textbox control retains the same name as your Web control (UniqueID); no “:childname” or “_childname” is concatenated. The reason for this has to do with making the Web control compatible with client-side validators and will be explained later.

What Do We Have So Far?
Compile your control and see what it looks like in a designer. I’ll leave it up to you to have an ASP.NET Web application ready to go with a test page so you can test your controls. Add the control to the toolbox by browsing for the compiled assembly. If you drag your new control onto a Web Form, you should get something that looks like Figure 3.

?
Figure 3: The FormField control in its first stage.

I think that looks pretty good for so little effort. Of course, you should fix a couple of details before you add any bells and whistles. First, I’ll show you how to fix the control visually so it looks cleaner. You can simply add a space between the caption and textbox and between the textbox and button. If you recall the last code snippet, you used three RenderBeginTags and RenderEndTags to render the three HTML tags. Now you need to add code to render a space character after the RenderEndTag that corresponds to the “span” tag and after the RenderEndTag that corresponds to the “input” tag for the textbox. You can use the Write method of the HtmlTextWriter object. In this method call you can send any literal text you want; in this case you’ll send  , which is the HTML control code for a space character. In C# your code would look like this.

   output.Write("  ");

For VB.NET code you just remove the trailing semi-colon. If you recompile your control and look at your Web Form now you’ll see the space between each of the elements of your control. If you modify the properties of the control a little bit, you’ll see the Caption and ButtonCaption properties in the Appearance category of the property browser. Change the Caption to “Enter name:” and the ButtonCaption to “search” and you should see something like what’s in Figure 4.

?
Figure 4: The FormField control in progress.

I think by now you can see how useful this can be. In fact, at this point you can use the control on a Web Form and see it in action. The Text property can retrieve or set the textbox’s value from the form’s code-behind page. But for real versatility, you still have a little more work to do.

To Be or Not Be
It’s pretty obvious that few if not most of the instances of this control that you would use in an actual Web Form don’t need the button to the right of the textbox. You could take all the code in the Render method that corresponds to the button, including the space character you rendered before it, and place it around a condition statement that checks a new Boolean property called ButtonVisible. This lets you toggle the visibility of the button on your FormField control. However, in the downloadable code for this article, you’ll notice that I don’t use a ButtonVisible property. Instead, I’ve added a little more versatility with a property called ButtonLocation which is an enum value with three possibilities: Right, Left, or Hide.

Using this approach I can place the button either to the right or left of the textbox, or I can hide it altogether. The logic to achieve this functionality involves creating conditions for rendering the HTML in the Render event and doing things in a different order depending on certain property values. I won’t go into those details here but I suggest you review the downloadable code. You’ll find this and plenty of other added functionality.

In the second part of this article, I’ll show you three more things you can do to this control to make it really useful. First I’ll show you how to add the ability to capture an event when the button is clicked or when the text in the textbox changes. In addition, I’ll show you how to add basic styling, and I’ll show you how to allow each element that makes up your control resize appropriately. In the mean time, feel free to read ahead in the code samples.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Related Posts