Skip navigation.

One Good Use of SilverlightAll recent postsCraving For Language Expressiveness

Taming DataList With a Custom Adapter

Suppose you want to extend a DataList and have it put out a div for each row. The RepeatLayout property can be either Flow (“Items are displayed without a table structure”) or Table (“Items are displayed in a table”). Since we want divs, we’re after RepeatLayout = RepeatLayout.Flow. Not so fast, though. This control isn’t that easy to extend.

What you get is a <span> which wraps the rest of the markup. More so, <div> rows are separated with superfluous <br>s that come out of nowhere!

<span id="foo">
    <div class="bar"></div>
    <br>
    <div class="bar"></div>
    <br>
    <div class="bar"></div>
    <br>
</span>

The first impulse is to override the TagKey property:

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

Just about every control will yield and render what you tell it, but not DataList. Beat your head against the wall—you still get a <span>. How weird is it to have an inline element wrap a block element!

My next guess was to look inside the ASP.NET CSS Friendly Control Adapters, but I was in for a disappointment. The DataListAdapter does not accommodate the “flow” layout. It merely produces a cleaner <table>. Back to the drawing board.

Eventually, I wrote my own, simple adapter:

namespace MyNamespace
{
  public class MyListControlAdapter : WebControlAdapter
  {
    protected override void RenderContents (HtmlTextWriter w)
    {
       DataList dataList = Control as DataList;

       if (dataList != null)
       {
          foreach (DataListItem li in dataList.Items)
              li.RenderControl (w);
       }
       else
       {
          base.RenderContents (w);
       }
    }
  }
}

which produced pristine markup:

<div id="foo">
   <div class="bar"></div>
   <div class="bar"></div>
   <div class="bar"></div>
</div>

Remember to create, or edit, a file named default.browser in the App_Browsers folder and add the following section:

<browsers>
  <browser refID="Default">
    <controlAdapters>
    <adapter
      controlType="MyNamespace.MyListControl"
      adapterType="MyNamespace.MyListControlAdapter" />
    </controlAdapters>
  </browser>
</browsers>

Hope this tip saves someone a day or two of head beating.

Comments

Comment permalink 1 Phil |
Great article except this still produces a span for me as the DataListItem TagKey is still coming through as SPAN not DIV.

I've tried overriding DataListItem in the same manner as DataList but this simply does not work.

Am I missing some way of changing the TagKey property of DataListItem?

Rendered HTML goes div (items) -> span -> div (item) -> close div (item) -> close span -> close div (items)

(Can't post HTML).

I agree that it is seriously frustrating that they decided to put an inline element in rather than just using a DIV in the first place!

Thanks
Phil
Comment permalink 2 Eric Kinateder |
Is there a reason you wouldn't use a Repeater server control instead?
Comment permalink 3 Milan Negovan |
Yep, paging, sorting, etc.
Comment permalink 4 Milan Negovan |
I take it back. I didn't need paging and sorting in this case. I needed the DataKeys collection.
Comment permalink 5 Paul |
Any solution for ye olde .net 1.1?

Emails and Notifications

Would you like to be notified when somebody responds to this post?  Would you like to have these comments emailed to you?

TrackBacks

Sorry, TrackBacks are not allowed.

Submit your comment

Please enter only text since all HTML tags except hyperlinks will be stripped. Hyperlinks will become live links. Any comments with flaming or offensive language will be deleted. Be courteous to other posters. Thank you.

Your name (required):
Your email (optional):
Your site's URL (optional):
Enter this number
Type in the number above:
Comment (required):