Blog

Clean ASP.Net control rendering, another way

After reading Joe Audette «Cleaner Rendering of ASP.NET Server Controls Coming Soon!» blog post I was sad I were developing with ASP.Net 1.1 and that would be a very nice addition to my current project(s).

ASP.Net 2.0 has good support to change the rendering of controls, yet I found that the same is possible to do with ASP.Net 1.1 and, although the same tecnique is present in 2.0, this is an approach that serves better some purposes as we’ll see.

The magic method is System.Web.UI.Control.SetRenderMethodDelegate (RenderMethod renderMethod) where RenderMethod is a delegate with the following signature: void RenderMethod(HtmlTextWriter output, Control container).

An example:

public void MyRenderMethod (HtmlTextWriter writer, System.Web.UI.Control control)
{
writer.Write (String.Format (“<table border=’1′><tr><td>{0}</td><td>”, control.ID));
foreach (System.Web.UI.Control ctrl in control.Controls)
ctrl.RenderControl (writer);
writer.Write (“</td></tr></table>”);
}
private void Page_Load(object sender, System.EventArgs e)
{
this.SetRenderMethodDelegate (new System.Web.UI.RenderMethod (MyRenderMethod));
}

This will make that each control you’ve in your page will be transformed into a table with the control id in the first cell and the actual control in the second cell.

This tecnique is somehow limited because it basicly works for child controls only. This means that if you apply this tecnique to one Label, it won’t call your method unless the Label actually has child controls (using label.Controls.Add method). Also, it doesn’t work recursively into controls child controls, meaning that if you have a datagrid its childs won’t be rendered with your method.
While this is somehow limited it allows you a larger control. It would be very easy to make it work recursively and make it check for an index of Control Adapters, imitating the 2.0 behaviour.

There are also two uses that come to my mind: themes and ASP.Net designers. Themes because you can control the actual rendering process of the controls and add everything you wish to them, something already present in 2.0 but not 1.1. ASP.Net designer because it allows you to render the wrapper html/js you need to make your design-time controls selectable, dragable and resizeable.

Pretty nice, no?

PS: At CJ’s request (see comments) I’m showing an image where I’ve used this tecnique to theme a textbox. It is base on the code above but using a 3×3 table and placing the right images in the right cells.

Themed label

Post to Twitter Post to Delicious Post to Digg Post to Facebook Post to Reddit Post to StumbleUpon

8 Responses to “Clean ASP.Net control rendering, another way”

  1. C.J. says:

    I want screenshots!

  2. Joe Audette says:

    Hi Alexandre,

    Thats a very interesting technique! However, if you want
    clean markup, the last thing you would do is wrap a table around an input control just to style it. The idea is to reduce the non-semantic markup as much as possible and stay away from using tables
    for layout or design effects. The only correct use of tables is for displaying tabular data. Though it is true that historically web designers have used tables for all kinds of layout and design, the
    idea of standards compliance is to not do such things. So markup that does use tables this way would not be considered clean, at least from my point of
    view.

    Cheers,

    Joe

  3. alexmipego says:

    Hey Joe,

    First, this is an
    example, I could use it to generate the html myself – which would be an improvement to ASP.Net 1.1 controls that don’t behave correctly under FF.

    About the eternal question: Tableless, to be
    or not to be? – Well, I’ve to admit I’m a table fan and altough I’m developing a ASP.Net web-based designer which creates pages with layers (optional of course), I’ve to say that I still love
    tables.

    I really understand the problem with table-based designs, but I also know that it is much easier and more cross-browser compatible.

  4. Joe Audette says:

    Hi Alexandre,

    Please forgive me I’m not trying to criticise but the whole point of why I’m looking forward to the CSS Control Adpaters and why it makes
    cleaner markup is that it gets rid of a whole bunch of nasty pointless tables. Tables seems like an easy way to do layout but there are better ways that are more accessible and more cross browser.
    Tables make things more difficult for screen readers and browsers in small devices like pdas and cell phones.

    With the CSS Control adapter the 2.0 Menu Control can render as a list of ul and
    li elements instead of a table and that is why it is cleaner. ul and li is the appropriate tags to use for a menu because it is a list of links, ul an li add semantic meaning to it by showing it is a
    list of links. Tables do not and are therefore non-sematic extra markup to be avoided in clean markup of a menu.

    What you are doing above is in no way the same thing that the CSS Control
    Adapter does in 2.0 .NET. The CSS Control Adapter actually changes the rendering of the control, what you are doing is wrapping the control in additional markup, in this case a table, which does not
    change what the control renders as. The same effect for what you are doing is just to put the table right in the markup around your control and there is really no benefit to hard coding the table in
    a render delegate. Its much easier to change if its in the markup.

    I’m not trying to be difficult :), hope you take my comment as contructive.

    Cheers,

    Joe

  5. Joe Audette says:

    I take it back about the hard coding, that was too harsh sorry. It is legit to put markup there my main point is really its just a wrapper not the same as changing
    the rendering itself.

    Anyway there are a lot of tables in the world and a few more won’t hurt anything. :)

    Cheers,

    Joe

  6. alexmipego says:

    I mean,
    thats just a sample use. I was to implement the thing for the menu you’re doing instead of wrapping the control with a table I would do the rendering myself.

    Instead of using the
    control.Render method I would do a for each menu item it contains and render ul and il stuff. Thats in this way that it would compare directly to your tecnique.

    As I say in the post, this
    tecnique *can* do almost the same than yours, but it is 1.1 compatible and it is better for another things. I guess the best example is really the ASP.Net Designer where I’ll be using this to render
    layers – yhe, no tables :) – arround the design-time html for the controls.

  7. Monoman says:

    Hi Alexandre,

    Back some 5 years, I and friend wrote a ASP
    designer, in ASP + VB6, using just divs, js and css and what they call today AJAX, so one could design tabbed web forms in real-time directly in the browser, dragging fields from the business
    objects’ representations…

    Well, someday, I may implement it for ASP.NET, but back to the subject here: I could implement the whole kaboodle with no tables, just CSS…

  8. Jeff Handley says:

    Alexandre,

    I came across this posting last night and it
    sparked an idea for me for a problem I had been trying to solve regarding DataGrid ItemCommand events with ViewState disabled. I gave you credit for pointing me at SetRenderMethodDelegate.
    Thanks!

    You can read the article here: http://jeffhandley.blogspot.com/2006/05/datagrid-itemcommand-without-viewstate.html

    Jeff Handley
    http://www.jeffhandley.com

Leave a Reply

For spam filtering purposes, please copy the number 8664 to the field below: