将asp:DataPager格式化为ul li显示

13
我正在使用Twitter Bootstrap和ASP.Net C# Webforms构建网站。我在页面上有一个ListView,其中绑定了一个DataPager,但我需要更改.NET呈现DataPager的HTML的方式。
目前,所有分页器项都显示为以下内容:
<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>

然而,我需要将所有的项目都包裹在无序列表中,而不是span和a标签。我的当前标记看起来像这样:

<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>

我需要覆盖NextPreviousPagerField和NumericPagerField,以便它们输出<li>标签而不是<span>和<a>。


你能提供一下你代码中添加的CSS吗?我需要它。 - Sunny Sandeep
4个回答

14

DataPager不原生支持此功能,因此您需要一个自定义控件。幸运的是,实现起来非常容易!

对于每个DataPagerFieldDataPager将向其自己的控件集合添加一个DataPagerFieldItem控件,然后告诉该字段在该项内创建其控件。内置字段会在按钮之间添加不间断空格(除非您将RenderNonBreakingSpacesBetweenControls属性设置为false),但它们很容易识别和抑制。

这个控件仍然会呈现启用按钮的<a>标记和当前页面数字的<span>标记,但应该接近您需要的内容:

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输出:

<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>

谢谢。我该如何使用自定义控件? - Chris
1
根据您的设置而定。对于网站项目,最简单的方法是将控件保存在您的 App_Code 文件夹中,在页面中添加 <%@ Register ... %> 指令(或将其添加到 web.config 文件的 system.web/pages/controls 部分),然后在页面中用 site:UnorderedListDataPager 替换 asp:DataPager - Richard Deeming
@RichardDeeming,我也在尝试为我的项目制作自定义DataPager,但出现了一些意外问题。您能否帮我看一下?http://stackoverflow.com/questions/21823583/issues-with-custom-datapager - JW Lim

9
我有一个稍微不同的解决方案。我对标记进行了一些调整,而不是更改DataPager的呈现方式,并且在呈现方面,它仍然看起来“类似于bootstrap”,即使它没有带有分页类的UL / LI标签。
非常重要的一点(如https://dev59.com/zW035IYBdhLWcg3wPNZk#19398488中所解释的)是更改asp.net输出的禁用控件的类,默认情况下为“aspNetDisabled”,但对于bootstrap而言,最好只使用“disabled”。在Global.asax的Application_Start中执行此操作。如果不这样做,则第一页、上一页、下一页和最后一页按钮将不会显示为禁用状态。
void Application_Start(object sender, EventArgs e)
{
    WebControl.DisabledCssClass = "customDisabledClassName";
}

来源: WebControl.DisabledCssClass属性(MSDN)

该属性获取或设置当Web服务器控件处于禁用状态时应用于控件的CSS类。此属性可用于在页面上更改禁用控件的外观。

    <asp:DataPager ID="it" runat="server" class="btn-group btn-group-sm">
        <Fields>
            <asp:NextPreviousPagerField PreviousPageText="<" FirstPageText="|<" ShowPreviousPageButton="true"
                ShowFirstPageButton="true" ShowNextPageButton="false" ShowLastPageButton="false"
                ButtonCssClass="btn btn-default" RenderNonBreakingSpacesBetweenControls="false" RenderDisabledButtonsAsLabels="false" />
            <asp:NumericPagerField ButtonType="Link" CurrentPageLabelCssClass="btn btn-primary disabled"  RenderNonBreakingSpacesBetweenControls="false"
                NumericButtonCssClass="btn btn-default" ButtonCount="10" NextPageText="..." NextPreviousButtonCssClass="btn btn-default" />
            <asp:NextPreviousPagerField NextPageText=">" LastPageText=">|" ShowNextPageButton="true"
                ShowLastPageButton="true" ShowPreviousPageButton="false" ShowFirstPageButton="false"
                ButtonCssClass="btn btn-default" RenderNonBreakingSpacesBetweenControls="false" RenderDisabledButtonsAsLabels="false"/>
        </Fields>
    </asp:DataPager>

以下是Asp.net服务器标记的呈现结果,它被渲染成分页器: asp.net server markup renders as this pager

这是渲染后的HTML:

<span id="ctl00_Body_CaseList918421504_ListControl_Pager_it" class="btn-group btn-group-sm">
    <a class="disabled btn btn-default">|&lt;</a>
    <a class="disabled btn btn-default">&lt;</a>
    <span class="btn btn-primary disabled">1</span>
    <a class="btn btn-default" href="javascript:__doPostBack('ctl00$Body$CaseList918421504_ListControl$Pager$it$ctl01$ctl01','')">2</a>
    <a class="btn btn-default" href="javascript:__doPostBack('ctl00$Body$CaseList918421504_ListControl$Pager$it$ctl01$ctl02','')">3</a>
    <a class="btn btn-default" href="javascript:__doPostBack('ctl00$Body$CaseList918421504_ListControl$Pager$it$ctl01$ctl03','')">4</a>
    <a class="btn btn-default" href="javascript:__doPostBack('ctl00$Body$CaseList918421504_ListControl$Pager$it$ctl01$ctl04','')">5</a>
    <a class="btn btn-default" href="javascript:__doPostBack('ctl00$Body$CaseList918421504_ListControl$Pager$it$ctl01$ctl05','')">6</a>
    <a class="btn btn-default" href="javascript:__doPostBack('ctl00$Body$CaseList918421504_ListControl$Pager$it$ctl01$ctl06','')">7</a>
    <a class="btn btn-default" href="javascript:__doPostBack('ctl00$Body$CaseList918421504_ListControl$Pager$it$ctl01$ctl07','')">8</a>
    <a class="btn btn-default" href="javascript:__doPostBack('ctl00$Body$CaseList918421504_ListControl$Pager$it$ctl01$ctl08','')">9</a>
    <a class="btn btn-default" href="javascript:__doPostBack('ctl00$Body$CaseList918421504_ListControl$Pager$it$ctl01$ctl09','')">10</a>
    <a class="btn btn-default" href="javascript:__doPostBack('ctl00$Body$CaseList918421504_ListControl$Pager$it$ctl01$ctl10','')">...</a>
    <a class="btn btn-default" href="javascript:__doPostBack('ctl00$Body$CaseList918421504_ListControl$Pager$it$ctl02$ctl00','')">&gt;</a>
    <a class="btn btn-default" href="javascript:__doPostBack('ctl00$Body$CaseList918421504_ListControl$Pager$it$ctl02$ctl01','')">&gt;|</a>
</span>

8
除了Richard的答案之外...我采用了他的方法,并添加了对“禁用”和“激活”类以及周围的div标签的支持-
更新:我添加了John的建议,将激活标签特殊呈现为超链接,以正确呈现pagination-sm和pagination-lg。因此,也要感谢John。
更新2:添加了控件的id呈现。感谢DGibbs。
    [
    Bindable(false),
    Category("Appearance"),
    DefaultValue("pagination pagination-centered"),
    Description("Css class for the surrounding div")
    ]
    public virtual string CssClass {
        get {
            if (ViewState["CssClass"] == null) {
                ViewState["CssClass"] = "pagination pagination-centered";
            }
            return (string)ViewState["CssClass"];
        }
        set {
            ViewState["CssClass"] = value;
        }
    }

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

    protected override void AddAttributesToRender(HtmlTextWriter writer) {
            if (HasControls()) {
                writer.AddAttribute("id", base.ClientID);
                writer.AddAttribute(HtmlTextWriterAttribute.Class, CssClass);
            }
    }

    protected override void RenderContents(HtmlTextWriter writer) {
        if (HasControls()) {
            writer.RenderBeginTag(HtmlTextWriterTag.Ul);

            foreach (Control child in Controls) {
                var item = child as DataPagerFieldItem;
                if (item == null || !item.HasControls()) {
                    child.RenderControl(writer);
                    continue;
                }

                foreach (Control ctrl in item.Controls) {
                    var space = ctrl as LiteralControl;
                    if (space != null && space.Text == "&nbsp;")
                        continue;

                    // Set specific classes for li-Tag
                    bool isCurrentPage = false
                    if (ctrl is System.Web.UI.WebControls.WebControl) {
                        // Enabled = false -> "disabled"
                        if (!((System.Web.UI.WebControls.WebControl)ctrl).Enabled) {
                            writer.AddAttribute(HtmlTextWriterAttribute.Class, "disabled");
                        }

                        // there can only be one Label in the datapager -> "active"
                        if (ctrl is System.Web.UI.WebControls.Label) {
                           isCurrentPage = true;                     
                           writer.AddAttribute(HtmlTextWriterAttribute.Class, "active");
                        }
                    }
                    writer.RenderBeginTag(HtmlTextWriterTag.Li);
                    // special rendering as hyperlink for current page
                    if (isCurrentPage) {
                        writer.AddAttribute(HtmlTextWriterAttribute.Href, "#");
                        writer.RenderBeginTag(HtmlTextWriterTag.A);
                    }
                    ctrl.RenderControl(writer);
                    if (isCurrentPage) {
                        writer.RenderEndTag(); // A
                    }
                    writer.RenderEndTag();
                }
            }

            writer.RenderEndTag();
        }
   }

这太棒了。对于使用AddAttributesToRender()方法的任何人,您可能需要包括writer.AddAttribute("id", base.ClientID);,因为在使用此方法时会丢失生成的控件id,这似乎会干扰内存分页(而不是查询字符串)。 - DGibbs

1

我对 Andreas 的回答进行了进一步修改。Bootstrap 示例将当前页(活动页)包装在超链接标记内,因此我注意到某些 Bootstrap 模板在选择分页-lg 或分页-sm 等大小变体时无法正确格式化活动标记。以下是我添加了额外超链接包装的 RenderContents 的版本:

    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 ctrl in item.Controls)
                {
                    var space = ctrl as LiteralControl;
                    if (space != null && space.Text == "&nbsp;")
                        continue;

                    // Set specific classes for li-Tag
                    var isCurrentPage = false;
                    if (ctrl is WebControl)
                    {
                        // Enabled = false -> "disabled"
                        if (!((WebControl)ctrl).Enabled)
                            writer.AddAttribute(HtmlTextWriterAttribute.Class, "disabled");

                        // there can only be one Label in the datapager -> "active"
                        if (ctrl is Label)
                        {
                            isCurrentPage = true;
                            writer.AddAttribute(HtmlTextWriterAttribute.Class, "active");
                        }
                    }

                    writer.RenderBeginTag(HtmlTextWriterTag.Li);
                    if (isCurrentPage)
                    {
                        writer.AddAttribute(HtmlTextWriterAttribute.Href, "#");
                        writer.RenderBeginTag(HtmlTextWriterTag.A);
                    }
                    ctrl.RenderControl(writer);
                    if (isCurrentPage)
                        writer.RenderEndTag();
                    writer.RenderEndTag();
                }
            }
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接