Search code examples
c#asp.nettwitter-bootstrapdatapager

Formatting an asp:DataPager to show in ul li


I am building a website using the Twitter Bootstrap and ASP.Net C# Webforms. I have a ListView on my page with a DataPager bound to it, but I need to change the way .Net renders the HTML of the DataPager.

Currently, all pager items are displaying like this:

<div class="clearfix pagination pagination-centered"> <span id="cpBody_dpListing"> <a class="aspNetDisabled">First</a>&nbsp;<span>1</span>&nbsp; <a href="javascript:__doPostBack('ctl00$cpBody$dpListing$ctl02$ctl01','')">2</a>&nbsp; <a href="javascript:__doPostBack('ctl00$cpBody$dpListing$ctl03$ctl00','')">Last</a>&nbsp; </span> </div>

however I need to wrap all my items in an unordered list rather than span and a tags. My current mark-up looks like this:

<div class="clearfix pagination pagination-centered">
<asp:DataPager ID="dpListing" runat="server" PagedControlID="lvListing" PageSize="10" OnPreRender="dpListing_PreRender">
    <Fields>
        <asp:TemplatePagerField>
            <PagerTemplate>
                <asp:BulletedList ID="listPages" runat="server" DisplayMode="LinkButton" OnClick="listPages_Click"></asp:BulletedList>
            </PagerTemplate>
        </asp:TemplatePagerField>
        <asp:NextPreviousPagerField ButtonType="Link" ShowFirstPageButton="true" ShowNextPageButton="false" ShowPreviousPageButton="false" />
        <asp:NumericPagerField PreviousPageText="&lt; Prev 10" NextPageText="Next 10 &gt;" ButtonCount="10" />
        <asp:NextPreviousPagerField ButtonType="Link" ShowLastPageButton="true" ShowNextPageButton="false" ShowPreviousPageButton="false" />
    </Fields>
</asp:DataPager>

I somehow need to override the NextPreviousPagerField and NumericPagerField so they output <li> tags rather than <span> and <a>.


Solution

  • The DataPager doesn't support this out of the box, so you're going to need a custom control. Fortunately, it's quite east to implement!

    For each DataPagerField, the DataPager adds a DataPagerFieldItem control to its own control collection, and then tells the field to create its controls within that item. The built-in fields will add non-breaking spaces between the buttons (unless you set the RenderNonBreakingSpacesBetweenControls property to false), but they're quite easy to identify and suppress.

    This control will still render the <a> tags for the enabled buttons and the <span> tag for the current page number, but should be close to what you need:

    public class UnorderedListDataPager : DataPager
    {
       protected override HtmlTextWriterTag TagKey 
       {
          get { return HtmlTextWriterTag.Ul; }
       }
    
       protected override void RenderContents(HtmlTextWriter writer)
       {
          if (HasControls())
          {
             foreach (Control child in Controls)
             {
                var item = child as DataPagerFieldItem;
                if (item == null || !item.HasControls())
                {
                    child.RenderControl(writer);
                    continue;
                }
    
                foreach (Control button in item.Controls)
                {
                   var space = button as LiteralControl;
                   if (space != null && space.Text == "&nbsp;") continue;
    
                   writer.RenderBeginTag(HtmlTextWriterTag.Li);
                   button.RenderControl(writer);
                   writer.RenderEndTag();
                }
             }
          }
       }
    }
    

    HTML output:

    <ul id="dpListing">
       <li><a class="aspNetDisabled">First</a></li>
       <li><span>1</span></li>
       <li><a href="javascript:__doPostBack('ctl00$cpBody$dpListing$ctl02$ctl01','')">2</a></li>
       <li><a href="javascript:__doPostBack('ctl00$cpBody$dpListing$ctl03$ctl00','')">Last</a></li>
    </ul>