Taming DataList With a Custom Adapter
Posted in Development
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.
7 comments
Eric Kinateder
on November 16, 2007
Is there a reason you wouldn't use a Repeater server control instead?
Milan Negovan
on November 19, 2007
Yep, paging, sorting, etc.
Milan Negovan
on November 19, 2007
I take it back. I didn't need paging and sorting in this case. I needed the DataKeys collection.
David Lewis
on November 20, 2009
This was a HUGE help... but I'm also still getting span tags. And I have to use a DataList. I can't use a Repeater. Any ideas?
Oblio
on March 31, 2010
I concur; I cannot replicate your results. Specifically, I do not believe it's possible; the rendering is done with the RepeaterInfo class and the is hard coded. See also: http://forums.asp.net/t/1477757.aspx

Phil
on November 12, 2007
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