Geeks With Blogs
ICaramba Miguel Castro's blog about .NET and its effect on National Security, the Eco-system, and his daughter's sleeping patterns.

And unfortunately, it's a detail I always seem to forget whenever I teach Webcontrol development.

Anyone who has ever taken my webcontrol class or has heard my user group presentations about them, knows that I start by telling you the simplest thing: webcontrols render HTML to the browser.  Now, while this has become pretty much common knowledge in the ASP.NET community, here's one detail that I haven't even seen the books tell.  A standard composite control inherits from the System.Web.UI.WebControl.  A very common practice is to build an HTML table inside your composite control to surround any child controls you may have.  The problem is that the WebControl class by default, renders the control container as a Span tag in HTML.  In fact if you create an empty WebControl with no children and run the page, you'll just see an empty Span tag.  The Span tag is an inline element, while the Table tag is a block element.  The HTML specification states that a block element cannot be contained inside an inline element - only the other way around.  For those that don't understand the difference:  the main characteristic of these two types of HTML elements is that inline elements can go next to each other, while block elements cannot.  Ever try putting two Tables next to each other?  Doesn't work.  You have to put them in side-by-side cells of another table.  So if you develop a composite control and build a table surrounding its child controls, you end up with illegal HTML.  The problem is that IE is so forgiving and lets you get away with it without screaming at you.  Well, the fix is easy.

If you inherit from the WebControl class, you need to override the default constructor of your control and call its base constructor with a certain argument:

Public Sub New()
     MyBase.New(HtmlTextWriterTag.Div)
End Sub

or

public WebControl1() : base(HtmlTextWriterTag.Div) { }

In the C# example, I am assuming the webcontrol class is called WebControl1.

Notice the argument I am sending into the base constructor.  It's an enum that Microsoft gives us for almost every HTML tag value.  In this case, we are changing the default tag that is rendered as the control container to Div.  Div is a block element and allows the legal containment of other block elements (or inline elements) such as the Table tag.

In ASP.NET 2.0, we have a new class from which to inherit composite controls; it's called CompositeControl.  This class does a few things automatically for you, such as calling EnsureChildControls before rendering and implementing INamingContainer.  But it does not correct the default container tag.  I say “the correct” one because my opinion is that the default tag for composite controls should be Div, not Span.  Overriding the default constructor on a webcontrol that inherits from the CompositeControl class does not work because it is not able to acces the overload with the argument we need.  In this case, we have a property we can override, called TagKey:

Protected Overrides ReadOnly Property TagKey() As System.Web.UI.HtmlTextWriterTag
     Get
         
Return
HtmlTextWriterTag.Div
     End
Get
End Property

or

protected override System.Web.UI.HtmlTextWriterTag TagKey
{
     get { return HtmlTextWriterTag.Div;
  }
}

In this case, we're achieving the same thing just in a different manner.

So the important thing to remember is to do this if you are going to start your Controls collection with a block element like Table.

Don't forget this !!!

 

Posted on Thursday, January 19, 2006 7:47 AM | Back to top

Copyright © Miguel A. Castro | Powered by: GeeksWithBlogs.net