Tuesday, October 17, 2006

[ASP.NET] Basic of Custom Server Control Development Part I

Developing custom server control in ASP.NET is fun! You are flexible to develop it either inheriting the existing ASP.NET server controls like Button, HyperLink, BoundField or create you own control by inheriting Control/WebControl classes from System.Web.UI namespace. There are dozens of cool and fabulous custom server controls developed by third-parties like Metabuilder or ExcentricWorld. I like to develop the custom server control because the tailored controls can specifically accomplish some jobs that normal shipped-in ASP.NET server controls can't. It serves the purpose on your needs.

There are basic concepts/rules in custom server control development in ASP.NET like :

1. Derive your control class from System.Web.UI.Control if your control is dealing with non-visual elements or merely render as HTML output. For instance, META tag. Otherwise, your class should inherit from System.Web.UI.WebControls class if your control is built to have visual appearance to the client.

2. Do not override the Render() method of in your control if it is inheriting from System.Web.UI.WebControls class because the method is responsible in rendering the outer tag and control styling to the output stream. Override its RenderContent() method instead!

protected override void RenderContent(HtmlTextWriter writer)
{
writer.Write("Test");
}


3. When your control inherting the System.Web.UI.WebControls, its outer tag is <span> by default. You can get rid of this and render any outer tags you want by overriding its HtmlTextWriterTag.TagKey or TagName (non-standard HTML tags).

protected override HtmlTextWriterTag TagKey
{
get { return HtmlTextWriterTag.Input; }
}

or

public Button() : base(HtmlTextWriterTag.Input)
{ }



4. Check whether the control is in the <form runat="server"> by

if (Page != null)
Page.VerifyRenderingInServerForm(this);


in either AddAttributesToRender() or Render()/RenderContent() method.


5. By default, the tag prefix of your custom server control would be auto-generated. For instance, when you drag and drop your control, the tag would be something like

<cc1:CustomMeta ID="CustomMetaTag1" runat="server" />

As you see, the "cc1" gives no meaning. You can add your own tag prefix by adding TagPrefixAttribute in the assemblyinfo.cs file.

using System.Web.UI;
[assembly:TagPrefix("SimpleControl", "Alvin")]

Now, it would become like

<Alvin:CustomMeta ID="CustomMetaTag1" runat="server" />


6. Take note of rendering methods of System.Web.UI.Control class

public void RenderControl(HtmlTextWriter writer) {
if (Visible) {
Render(writer);
}
}

protected virtual void Render(HtmlTextWriter writer) {
RenderChildren(writer);
}

protected virtual void RenderChildren(HtmlTextWriter writer) {
foreach (Control c in Controls) {
c.RenderControl(writer);
}
}


It is wise to call the base class's methods if you intend to override the method like RenderChildren method to ensure its child controls are recursively rendered.

protected override void RenderChildren(HtmlTextWriter writer)
{
base.RenderChildren(writer);

// do your stuff
}



7. To restrict the control to have NO CHILD CONTROLS, you need to return EmptyControlCollection(this) to the overidden CreateControlCollection() method.

protected override ControlCollection CreateControlCollection() {
return new EmptyControlCollection(this);
}


By doing that, no child controls/tags are allowed.

// Allow
<Alvin:CustomMeta ID="CustomMetaTag1" runat="server" />

// Not allow !
<Alvin:CustomMeta ID="CustomMetaTag1" runat="server"></Alvin:CustomMeta>

1 comment:

Anonymous said...
This comment has been removed by the author.