Login


A Self-Closing HtmlGenericControl

By Jonathan Wood on 3/3/2011 (Updated on 3/4/2011)
Language: C#
Technology: .NETWebForms
Platform: Windows
License: CPOL
Views: 24,777
Web Development » ASP.NET Controls » General » A Self-Closing HtmlGenericControl

Screenshot of Test Website

Download Source Code Download Source Code

Introduction

Although the WebForms designer make it very easy to create your page's markup at design time, it's sometimes necessary to create controls at run time.

For example, if the number or type of controls depend on information provided by the user, you might want to create those controls in your page's Load event handler. To create a control this way, you can just allocate a new control, set its properties, and add it to the Controls collection of a containing control. This technique is demonstrated in Listing 1.

Listing 1: Creating an ASP.NET Control Dynamically at Run Time

// Create a label control
Label label = new Label();
label.Text = "Here is a label control created at run time!";
Panel1.Controls.Add(label);

In some cases, you may want to use this same approach to create tags for which there is no specific .NET Framework control class. For example, there is no dedicated class for the <body> and <div> tags. In this case, you can use the HtmlGenericControl class instead.

The HtmlGenericControl Class

Normally, the HtmlGenericControl class is used to represent server-side tags that do not map directly to a specific HTML control. For example, consider the <div> tag shown in Listing 2.

Listing 2: A Server-Side Tag that Doesn't Map Directly to Any .NET Framework Control

<div id="mydiv" runat="server">
   ...
</div>

Because the <div> tag shown in Listing 2 has the runat="server" attribute, you can reference that control from code as shown in Listing 3.

Listing 3: Accessing a Server-Side HTML Tag from Code

mydiv.InnerText = "Hello, World!";

In this case, mydiv is of type HtmlGenericControl. This control is created automatically for server-side HTML tags that are not mapped to a specific ASP.NET server control. This is how HtmlGenericControl is most commonly used.

However, you can also use HtmlGenericControl to employ the technique shown in Listing 1 to create generic HTML markup. Listing 4 demonstrates this technique.

Listing 4: Creating a Generic HTML Tag Dynamically at Run Time

// Create paragraph tags
HtmlGenericControl ctl = new HtmlGenericControl("p");
ctl.InnerText = "Here are HTML tags created at run time!";
Panel1.Controls.Add(ctl);

This technique works well in cases where you need to create markup dynamically. However, there is one limitation to HtmlGenericControl: It always renders separate opening and closing tags. So, for example, if you use this class to render a paragraph tag, it renders as <p>...</p>. That's what you want, but what about tags such as <hr> or <br>? For these tags, you always want them to be self-closing so that they render as <hr /> instead of <hr>...</hr>.

The HtmlGenericSelfClosing Class

Listing 5 shows my HtmlGenericSelfClosing class. This class inherits from HtmlGenericControl, so it starts with all of that existing functionality. Then it overrides the Render() method so that it renders the entire control in one, self-closing tag.

It also overrides the Controls, InnerHtml, and InnerText properties. Because the tag is rendered as a single tag, there can be no "inner" content. The overrides for all of these properties raise an exception with a message that states this limitation.

Listing 5: The HtmlGenericSelfClosing Class

/// <summary>
/// Html generic control class that displays as self-closing tag
/// </summary>
public class HtmlGenericSelfClosing : HtmlGenericControl
{
    public HtmlGenericSelfClosing()
        : base()
    {
    }

    public HtmlGenericSelfClosing(string tag)
        : base(tag)
    {
    }

    protected override void Render(HtmlTextWriter writer)
    {
        writer.Write(HtmlTextWriter.TagLeftChar + this.TagName);
        Attributes.Render(writer);
        writer.Write(HtmlTextWriter.SelfClosingTagEnd);
    }

    public override ControlCollection Controls
    {
        get { throw new Exception("Self-closing tag cannot have child controls"); }
    }

    public override string InnerHtml
    {
        get { return String.Empty; }
        set { throw new Exception("Self-closing tag cannot have inner content"); }
    }

    public override string InnerText
    {
        get { return String.Empty; }
        set { throw new Exception("Self-closing tag cannot have inner content"); }
    }
}

Conclusion

Armed with the existing HtmlGenericControl class as well as the new HtmlGenericSelfClosing class, in addition to all the ASP.NET server controls, you have a large palette of classes to use when dynamically creating controls at run time. This should provide you with complete control over how the final HTML markup is rendered.

End-User License

Use of this article and any related source code or other files is governed by the terms and conditions of The Code Project Open License.

Author Information

Jonathan Wood

I'm a software/website developer working out of the greater Salt Lake City area in Utah. I've developed many websites including Black Belt Coder, Insider Articles, and others.