欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

AspNetPager分页控件源代码(Version 4.2)第1/2页

程序员文章站 2023-02-13 21:10:53
//aspnetpager分页控件源代码(version 4.2): using system; using system.io; using...
//aspnetpager分页控件源代码(version 4.2):

using system;
using system.io;
using system.web;
using system.web.ui;
using system.web.ui.webcontrols;
using system.web.ui.htmlcontrols;
using system.collections.specialized;
using system.text;
using system.componentmodel;
using system.componentmodel.design;
using system.collections;


namespace wuqi.webdiyer
{
 #region aspnetpager server control

 #region 控件说明及示例
 /// <summary>
 /// 用于asp.net web应用程序中对数据进行分页的的服务器控件。
 /// </summary>
 /// <remarks>不同于datagrid控件,aspnetpager分页控件本身并不显示任何数据,而只显示页导航元素,数据在页面上的显示方式与该控件无关。该控件可以为datagrid、datalist、repeater以及自定义控件进行分页,配合sql存储过程,分页性能较使用datagrid分页有明显提升,尤其是当数据量大时性能可提升数倍!
 /// <p>aspnetpager 2.0 中新增了通过url来分页的功能,这使得访问者可以直接输入相应的url来访问任何页面,并且搜索引擎也可以直接检索每个页面,若使用datagrid的分页功能,这是无法实现的。</p>
 /// <p>要使用 aspnetpager 分页控件,必须最少指定它的 <see cref="recordcount"/> 属性,指定并编写 <see cref="pagechanged"/> 事件的处理程序。
 /// <see cref="recordcount"/> 属性指定要分页的所有数据的总项数,若未指定该值或该值小于等于 <see cref="pagesize"/> ,则aspnetpager控件不会显示任何内容。
 /// 若未指定并编写 <see cref="pagechanged"/> 事件处理程序,则当用户点击页导航元素或在页索引文本框中手式输入页索引并提交时aspnetpager不会跳转到指定的页。
 /// aspnetpager控件的分页方法和datagrid基本相同,即在它的 <see cref="pagechanged"/> 事件处理程序中将传递事件数据的 <see cref="pagechangedeventargs"/> 的 <see cref="pagechangedeventargs.newpageindex"/>值赋给 aspnetpager的 <see cref="currentpageindex"/>属性,然后重新将新的数据与数据显示控件绑定。 </p></remarks>
 /// <example>以下示例说明如何用aspnetpager对datagrid进行分页。
 /// <code><![cdata[
 ///<%@ page language="c#"%>
 ///<%@ import namespace="system.data"%>
 ///<%@import namespace="system.data.sqlclient"%>
 ///<%@import namespace="system.configuration"%>
 ///<%@register tagprefix="webdiyer" namespace="wuqi.webdiyer" assembly="aspnetpager"%>
 ///<html>
 ///<head>
 ///<title>welcome to webdiyer.com </title>
 ///  <script runat="server">
 ///  sqlconnection conn;
 ///  sqlcommand cmd;
 ///  void page_load(object src,eventargs e)
 ///  {
 ///   conn=new sqlconnection(configurationsettings.appsettings["connstr"]);
 ///   if(!page.ispostback)
 ///   {
 ///    cmd=new sqlcommand("getnews",conn);
 ///    cmd.commandtype=commandtype.storedprocedure;
 ///    cmd.parameters.add("@pageindex",1);
 ///    cmd.parameters.add("@pagesize",1);
 ///    cmd.parameters.add("@docount",true);
 ///    conn.open();
 ///    pager.recordcount=(int)cmd.executescalar();
 ///    conn.close();
 ///    binddata();
 ///   }
 ///  }
 ///
 ///  void binddata()
 ///  {
 ///   cmd=new sqlcommand("getnews",conn);
 ///   cmd.commandtype=commandtype.storedprocedure;
 ///   cmd.parameters.add("@pageindex",pager.currentpageindex);
 ///   cmd.parameters.add("@pagesize",pager.pagesize);
 ///   cmd.parameters.add("@docount",false);
 ///   conn.open();
 ///   datagrid1.datasource=cmd.executereader();
 ///   datagrid1.databind();
 ///   conn.close();
 ///   pager.custominfotext="记录总数:<font color=\"blue\"><b>"+pager.recordcount.tostring()+"</b></font>";
 ///   pager.custominfotext+=" 总页数:<font color=\"blue\"><b>"+pager.pagecount.tostring()+"</b></font>";
 ///   pager.custominfotext+=" 当前页:<font color=\"red\"><b>"+pager.currentpageindex.tostring()+"</b></font>";
 ///  }
 ///  void changepage(object src,pagechangedeventargs e)
 ///  {
 ///   pager.currentpageindex=e.newpageindex;
 ///   binddata();
 ///  }
 ///  </script>
 ///     <meta http-equiv="content-language" content="zh-cn">
 ///  <meta http-equiv="content-type" content="text/html;charset=gb2312">
 ///  <meta name="generator" content="editplus">
 ///  <meta name="author" content="webdiyer(yhaili@21cn.com)">
 /// </head>
 /// <body>
 ///  <form runat="server" id="form1">
 ///   <asp:datagrid id="datagrid1" runat="server" />
 ///
 ///   <webdiyer:aspnetpager id="pager" 
 ///   runat="server" 
 ///   pagesize="8" 
 ///   numericbuttoncount="8" 
 ///   showcustominfosection="left" 
 ///   pagingbuttonspacing="0"
 ///   showinputbox="always" 
 ///   cssclass="mypager" 
 ///   horizontalalign="right" 
 ///   onpagechanged="changepage"  
 ///   submitbuttontext="转到" 
 ///   numericbuttontextformatstring="[{0}]"/>
 ///
 ///  </form>
 /// </body>
 ///</html>
 /// ]]>
 /// </code>
 /// <p>下面是该示例所用的sql server存储过程:</p>
 /// <code>
 /// <![cdata[
 ///create procedure getnews
 ///  (@pagesize int,
 ///  @pageindex int,
 ///  @docount bit)
 ///  as
 ///  set nocount on
 ///  if(@docount=1)
 ///  select count(id) from news
 ///  else
 ///  begin
 ///  declare @indextable table(id int identity(1,1),nid int)
 ///  declare @pagelowerbound int
 ///  declare @pageupperbound int
 ///  set @pagelowerbound=(@pageindex-1)*@pagesize
 ///  set @pageupperbound=@pagelowerbound+@pagesize
 ///  set rowcount @pageupperbound
 ///  insert into @indextable(nid) select id from news order by addtime desc
 ///  select o.id,o.source,o.title,o.addtime from news o,@indextable t where o.id=t.nid
 ///  and t.id>@pagelowerbound and t.id<=@pageupperbound order by t.id
 ///  end
 ///  set nocount off
 ///go
 /// ]]>
 /// </code></example>
 #endregion

 [defaultproperty("pagesize")]
 [defaultevent("pagechanged")]
 [parsechildren(false)]
 [persistchildren(false)]
 [description("专用于asp.net web应用程序的分页控件")]
 [designer(typeof(pagerdesigner))]
 [toolboxdata("<{0}:aspnetpager runat=server></{0}:aspnetpager>")]
 public class aspnetpager:panel,inamingcontainer,ipostbackeventhandler,ipostbackdatahandler
 {
  private string cssclassname;
  private string urlpageindexname="page";
  private bool urlpaging=false;
  private string inputpageindex;
  private string currenturl=null;
  private namevaluecollection urlparams=null;

  #region properties

  #region navigation buttons

  /// <summary>
  /// 获取或设置一个值,该值批示当鼠标指针悬停在导航按钮上时是否显示工具提示。
  /// </summary>
  [browsable(true),
  category("导航按钮"),
  defaultvalue(true),
  description("指定当鼠标停留在导航按钮上时,是否显示工具提示")]
  public bool shownavigationtooltip
  {
   get
   {
    object obj=viewstate["shownavigationtooltip"];
    return (obj==null)?true:(bool)obj;
   }
   set
   {
    viewstate["shownavigationtooltip"]=value;
   }
  }

  /// <summary>
  /// 获取或设置导航按钮工具提示文本的格式。
  /// </summary>
  [browsable(true),
  category("导航按钮"),
  defaultvalue("转到第{0}页"),
  description("页导航按钮工具提示文本的格式")]
  public string navigationtooltiptextformatstring
  {
   get
   {
    object obj=viewstate["navigationtooltiptextformatstring"];
    return (obj==null)?"转到第{0}页":(string)obj;
   }
   set
   {
    string tip=value;
    if(tip.trim().length<1&&tip.indexof("{0}")<0)
     tip="{0}";
    viewstate["navigationtooltiptextformatstring"]=tip;
   }
  }

  /// <summary>
  /// 获取或设置一个值,该值指示是否将页索引按钮用中文数字代替。
  /// </summary>
  /// <remarks>
  /// 将该值设为true并且未使用图片按钮时,页索引按钮中的数值1、2、3等将会被中文字符一、二、三等代替。
  /// </remarks>
  [browsable(true),
  category("导航按钮"),
  defaultvalue(false),
  description("是否将页索引数值按钮用中文数字一、二、三等代替")]
  public bool chinesepageindex
  {
   get
   {
    object obj=viewstate["chinesepageindex"];
    return (obj==null)?false:(bool)obj;
   }
   set
   {
    viewstate["chinesepageindex"]=value;
   }
  }

  /// <summary>
  /// 获取或设置页索引数值导航按钮上文字的显示格式。
  /// </summary>
  /// <value>
  /// 字符串,指定页索引数值按钮上文字的显示格式,默认值为<see cref="string.empty"/>,即未设置该属性。</value>
  /// <remarks>
  /// 使用numericbuttontextformatstring属性指定页索引数值按钮的显示格式,如未设置该值时索引按钮文本将会是:1 2 3 ...,设置该值将改变索引按钮文本的显示格式,
  /// 如将该值设为“[{0}]”则索引文本会显示为:[1] [2] [3] ...,将该值设为“-{0}-”则会使索引文本变为:-1- -2- -3- ...。
  /// </remarks>
  [browsable(true),
  defaultvalue(""),
  category("导航按钮"),
  description("页索引数值按钮上文字的显示格式")]
  public string numericbuttontextformatstring
  {
   get
   {
    object obj=viewstate["numericbuttontextformatstring"];
    return (obj==null)?string.empty:(string)obj;
   }
   set
   {
    viewstate["numericbuttontextformatstring"]=value;
   }
  }

  /// <summary>
  /// 获取或设置分页导航按钮的类型,即使用文字还是图片。
  /// </summary>
  /// <remarks>
  /// 要使用图片按钮,您需要准备以下图片:从0到9的十个数值图片(当showpageindex设为true时),第一页、上一页、下一页、最后一页及更多页(...)五个按钮图片(当showfirstlast及showprevnext都设为true时),
  /// 若需要使当前页索引的数值按钮不同于别的页索引数值按钮,则还需准备当前页索引的按钮图片;
  /// 若需要使已禁用的第一页、上一页、下一页及最后一页按钮图片不同于正常的按钮图片,则还需准备这四个按钮在禁用状态下的图片;
  /// <p><b>图片文件的命名规则如下:</b></p>
  /// <p>从0到9十张数值按钮图片必须命名为“数值+buttonimagenameextension+buttonimageextension”,其中的buttonimagenameextension可以不用设置,
  /// buttonimageextension是图片文件的后缀名,如 .gif或 .jpg等可以在浏览器中显示的任何图片文件类型。如页索引“1”的图片文件可命名为“1.gif”或“1.jpg”,
  /// 当您有两套或更多套图片文件时,可以通过指定buttonimagenameextension属性值来区分不同套的图片,如第一套图片可以不用设buttonimagenameextension,则图片文件名类似于“1.gif”、“2.gif”等等,而第二套图片则设置buttonimagenameextension为“f”,图片文件名类似于“1f.gif”,“2f.gif”等等。</p>
  /// <p>第一页按钮的图片文件名以“first”开头,上一页按钮图片名以“prev”开头,下一页按钮图片名以“next”开头,最后一页按钮图片名以“last”开头,更多页按钮图片名以“more”开头,是否使用buttonimagenameextension取决于数值按钮的设置及是否有更多套图片。</p>
  /// </remarks>
  /// <example>
  /// 以下代码片段示例如果使用图片按钮:
  /// <p>
  /// <code><![cdata[
  /// <webdiyer:aspnetpager runat="server" 
  ///  id="pager1" 
  ///  onpagechanged="changepage"  
  ///  pagingbuttontype="image" 
  ///  imagepath="images" 
  ///  buttonimagenameextension="n" 
  ///  disabledbuttonimagenameextension="g" 
  ///  buttonimageextension="gif" 
  ///  cpibuttonimagenameextension="r" 
  ///  pagingbuttonspacing=5/>
  /// ]]>
  /// </code>
  /// </p>
  /// </example>
  [browsable(true),
  defaultvalue(pagingbuttontype.text),
  category("导航按钮"),
  description("分页导航按钮的类型,是使用文字还是图片")]
  public pagingbuttontype pagingbuttontype
  {
   get
   {
    object obj=viewstate["pagingbuttontype"];
    return (obj==null)?pagingbuttontype.text:(pagingbuttontype)obj;
   }
   set
   {
    viewstate["pagingbuttontype"]=value;
   }
  }

  /// <summary>
  /// 获取或设置页导航数值按钮的类型,该值仅当pagingbuttontype设为image时才有效。
  /// </summary>
  /// <remarks>
  /// 当您将pagingbuttontype设为image当又不想让页索引数值按钮使用图片时,可以将该值设为text,这会使页索引数据按钮使用文本而不是图片按钮。
  /// </remarks>
  [browsable(true),
  defaultvalue(pagingbuttontype.text),
  category("导航按钮"),
  description("页导航数值按钮的类型")]
  public pagingbuttontype numericbuttontype
  {
   get
   {
    object obj=viewstate["numericbuttontype"];
    return (obj==null)?pagingbuttontype:(pagingbuttontype)obj;
   }
   set
   {
    viewstate["numericbuttontype"]=value;
   }
  }

  /// <summary>
  /// 获取或设置第一页、上一页、下一页和最后一页按钮的类型,该值仅当pagingbuttontype设为image时才有效。
  /// </summary>
  /// <remarks>
  /// 当您将pagingbuttontype设为image但又不想让第一页、下一页、下一页和最后一页按钮使用图片,则可以将该值设为text,这会使前面的四个按钮使用文本而不是图片按钮。
  /// </remarks>
  [browsable(true),
  category("导航按钮"),
  defaultvalue(pagingbuttontype.text),
  description("第一页、上一页、下一页和最后一页按钮的类型")]
  public pagingbuttontype navigationbuttontype
  {
   get
   {
    object obj=viewstate["navigationbuttontype"];
    return (obj==null)?pagingbuttontype:(pagingbuttontype)obj;
   }
   set
   {
    viewstate["navigationbuttontype"]=value;
   }
  }

  /// <summary>
  /// 获取或设置“更多页”(...)按钮的类型,该值仅当pagingbuttontype设为image时才有效。
  /// </summary>
  /// <remarks>
  /// 当您将pagingbuttontype设为image但又不想让更多页(...)按钮使用图片时,可以将此值设为text,这会使更多页按钮使用文本而不是图片按钮。
  /// </remarks>
  [browsable(true),
  category("导航按钮"),
  defaultvalue(pagingbuttontype.text),
  description("“更多页”(...)按钮的类型")]
  public pagingbuttontype morebuttontype
  {
   get
   {
    object obj=viewstate["morebuttontype"];
    return (obj==null)?pagingbuttontype:(pagingbuttontype)obj;
   }
   set
   {
    viewstate["morebuttontype"]=value;
   }
  }

  /// <summary>
  /// 获取或设置分页导航按钮之间的间距。
  /// </summary>
  [browsable(true),
  category("导航按钮"),
  defaultvalue(typeof(unit),"5px"),
  description("分页导航按钮之间的间距")]
  public unit pagingbuttonspacing
  {
   get
   {
    object obj=viewstate["pagingbuttonspacing"];
    return (obj==null)?unit.pixel(5):(unit.parse(obj.tostring()));
   }
   set
   {
    viewstate["pagingbuttonspacing"]=value;
   }
  }

  /// <summary>
  /// 获取或设置一个值,该值指示是否在页导航元素中显示第一页和最后一页按钮。
  /// </summary>
  [browsable(true),
  description("是否在页导航元素中显示第一页和最后一页按钮"),
  category("导航按钮"),
  defaultvalue(true)]
  public bool showfirstlast
  {
   get
   {
    object obj=viewstate["showfirstlast"];
    return (obj==null)?true:(bool)obj;
   }
   set{viewstate["showfirstlast"]=value;}
  }

  /// <summary>
  /// 获取或设置一个值,该值指示是否在页导航元素中显示上一页和下一页按钮。
  /// </summary>
  [browsable(true),
  description("是否在页导航元素中显示上一页和下一页按钮"),
  category("导航按钮"),
  defaultvalue(true)]
  public bool showprevnext
  {
   get
   {
    object obj=viewstate["showprevnext"];
    return (obj==null)?true:(bool)obj;
   }
   set{viewstate["showprevnext"]=value;}
  }

  /// <summary>
  /// 获取或设置一个值,该值指示是否在页导航元素中显示页索引数值按钮。
  /// </summary>
  [browsable(true),
  description("是否在页导航元素中显示数值按钮"),
  category("导航按钮"),
  defaultvalue(true)]
  public bool showpageindex
  {
   get
   {
    object obj=viewstate["showpageindex"];
    return (obj==null)?true:(bool)obj;
   }
   set{viewstate["showpageindex"]=value;}
  }

  /// <summary>
  /// 获取或设置为第一页按钮显示的文本。
  /// </summary>
  [browsable(true),
  description("第一页按钮上显示的文本"),
  category("导航按钮"),
  defaultvalue("<font face=\"webdings\">9</font>")]
  public string firstpagetext
  {
   get
   {
    object obj=viewstate["firstpagetext"];
    return (obj==null)?"<font face=\"webdings\">9</font>":(string)obj;
   }
   set{viewstate["firstpagetext"]=value;}
  }

  /// <summary>
  /// 获取或设置为上一页按钮显示的文本。
  /// </summary>
  [browsable(true),
  description("上一页按钮上显示的文本"),
  category("导航按钮"),
  defaultvalue("<font face=\"webdings\">3</font>")]
  public string prevpagetext
  {
   get
   {
    object obj=viewstate["prevpagetext"];
    return (obj==null)?"<font face=\"webdings\">3</font>":(string)obj;
   }
   set{viewstate["prevpagetext"]=value;}
  }

  /// <summary>
  /// 获取或设置为下一页按钮显示的文本。
  /// </summary>
  [browsable(true),
  description("下一页按钮上显示的文本"),
  category("导航按钮"),
  defaultvalue("<font face=\"webdings\">4</font>")]
  public string nextpagetext
  {
   get
   {
    object obj=viewstate["nextpagetext"];
    return (obj==null)?"<font face=\"webdings\">4</font>":(string)obj;
   }
   set{viewstate["nextpagetext"]=value;}
  }

  /// <summary>
  /// 获取或设置为最后一页按钮显示的文本。
  /// </summary>
  [browsable(true),
  description("最后一页按钮上显示的文本"),
  category("导航按钮"),
  defaultvalue("<font face=\"webdings\">:</font>")]
  public string lastpagetext
  {
   get
   {
    object obj=viewstate["lastpagetext"];
    return (obj==null)?"<font face=\"webdings\">:</font>":(string)obj;
   }
   set{viewstate["lastpagetext"]=value;}
  }

  /// <summary>
  /// 获取或设置在 <see cref="aspnetpager"/> 控件的页导航元素中同时显示的数值按钮的数目。
  /// </summary>
  [browsable(true),
  description("要显示的页索引数值按钮的数目"),
  category("导航按钮"),
  defaultvalue(10)]
  public int numericbuttoncount
  {
   get
   {
    object obj=viewstate["numericbuttoncount"];
    return (obj==null)?10:(int)obj;
   }
   set{viewstate["numericbuttoncount"]=value;}
  }

  /// <summary>
  /// 获取或设置一个值,该值指定是否显示已禁用的按钮。
  /// </summary>
  /// <remarks>
  /// 该值用来指定是否显示已禁用的分页导航按钮,当当前页为第一页时,第一页和上一页按钮将被禁用,当当前页为最后一页时,下一页和最后一页按钮将被禁用,被禁用的按钮没有链接,在按钮上点击也不会有任何作用。
  /// </remarks>
  [browsable(true),
  category("导航按钮"),
  description("是否显示已禁用的按钮"),
  defaultvalue(true)]
  public bool showdisabledbuttons
  {
   get
   {
    object obj=viewstate["showdisabledbuttons"];
    return (obj==null)?true:(bool)obj;
   }
   set
   {
    viewstate["showdisabledbuttons"]=value;
   }
  }

  #endregion

  #region image buttons

  /// <summary>
  /// 获取或设置当使用图片按钮时,图片文件的路径。
  /// </summary>
  [browsable(true),
  category("图片按钮"),
  description("当使用图片按钮时,指定图片文件的路径"),
  defaultvalue(null)]
  public string imagepath
  {
   get
   {
    string imgpath=(string)viewstate["imagepath"];
    if(imgpath!=null)
     imgpath=this.resolveurl(imgpath);
    return imgpath;
   }
   set
   {
    string imgpath=value.trim().replace("\\","/");
    viewstate["imagepath"]=(imgpath.endswith("/"))?imgpath:imgpath+"/";
   }
  }

  /// <summary>
  /// 获取或设置当使用图片按钮时,图片的类型,如gif或jpg,该值即图片文件的后缀名。
  /// </summary>
  [browsable(true),
  category("图片按钮"),
  defaultvalue(".gif"),
  description("当使用图片按钮时,图片的类型,如gif或jpg,该值即图片文件的后缀名")]
  public string buttonimageextension
  {
   get
   {
    object obj=viewstate["buttonimageextension"];
    return (obj==null)?".gif":(string)obj;
   }
   set
   {
    string ext=value.trim();
    viewstate["buttonimageextension"]=(ext.startswith("."))?ext:("."+ext);
   }
  }

  /// <summary>
  /// 获取或设置自定义图片文件名的后缀字符串,以区分不同类型的按钮图片。
  /// </summary>
  /// <remarks><note>注意:</note>该值不是文件后缀名,而是为区分不同的图片文件而在图片名中加入的字符串,如:
  /// 当前有两套按钮图片,其中一套中的“1”的图片名可为“1f.gif”,另一套中的“1”的图片名可起为“1n.gif”,其中的f和n即为buttonimagenameextension。</remarks>
  [browsable(true),
  defaultvalue(null),
  category("图片按钮"),
  description("自定义图片文件名的后缀字符串(非文件后缀名),如图片“1f.gif”的buttonimagenameextension即为“f”")]
  public string buttonimagenameextension
  {
   get
   {
    return (string)viewstate["buttonimagenameextension"];
   }
   set
   {
    viewstate["buttonimagenameextension"]=value;
   }
  }

  /// <summary>
  /// 获取或设置当前页索引按钮的图片名后缀。
  /// </summary>
  /// <remarks>
  /// 当 <see cref="pagingbuttontype"/> 设为 image 时,该属性允许您设置当前页索引数值按钮使用的图片名后缀字符,因此可以使当前页索引按钮与其它页索引按钮使用不同的图片,若未设置该值,则默认值为<see cref="buttonimagenameextension"/>,即当前页索引按钮与其它页索引按钮使用相同的图片。
  /// </remarks>
  [browsable(true),
  defaultvalue(null),
  category("图片按钮"),
  description("当前页索引按钮的图片名后缀字符串")]
  public string cpibuttonimagenameextension
  {
   get
   {
    object obj=viewstate["cpibuttonimagenameextension"];
    return (obj==null)?buttonimagenameextension:(string)obj;
   }
   set
   {
    viewstate["cpibuttonimagenameextension"]=value;
   }
  }

  /// <summary>
  /// 获取或设置已禁用的页导航按钮图片名后缀字符串。
  /// </summary>
  /// <remarks>
  /// 当 <see cref="pagingbuttontype"/> 设为 image 时, 该值允许您设置已禁用(即没有链接,因而点击后无反应)的页导航按钮(包括第一页、上一页、下一页、最后一页四个按钮)的图片文件名后缀字符串,因此可以使已禁用的页导航按钮不同于正常的页导航按钮。若未设置该值,则默认值为<see cref="buttonimagenameextension"/>,即已禁用的页导航按钮与正常的页导航按钮使用相同的图片。
  /// </remarks>
  [browsable(true),
  defaultvalue(null),
  category("图片按钮"),
  description("已禁用的页导航按钮的图片名后缀字符串")]
  public string disabledbuttonimagenameextension
  {
   get
   {
    object obj=viewstate["disabledbuttonimagenameextension"];
    return (obj==null)?buttonimagenameextension:(string)obj;
   }
   set
   {
    viewstate["disabledbuttonimagenameextension"]=value;
   }
  }
  /// <summary>
  /// 指定当使用图片按钮时,图片的对齐方式。
  /// </summary>

  [browsable(true),
  description("指定当使用图片按钮时,图片的对齐方式"),
  defaultvalue(imagealign.baseline),
  category("图片按钮")]
  public imagealign buttonimagealign
  {
   get
   {
    object obj=viewstate["buttonimagealign"];
    return (obj==null)?imagealign.baseline:(imagealign)obj;
   }
   set{viewstate["buttonimagealign"]=value;}
  }

  
  #endregion

  #region paging

  /// <summary>
  /// 获取或设置是否启用url来传递分页信息。
  /// </summary>
  /// <remarks>
  /// 启用url分页方式是将用户欲访问的页索引通过url来传递,由于该分页方式不使用页面向自身回发来传递数据,
  /// 所以每次分页时所有的数据都恢复为初始值或需要重新获取。使用url分页方式不支持动态改变分页控件的属性值,
  /// 因暂时无法将新的属性值通过url来传递给下一页。
  /// </remarks>
  /// <example>以下示例说明如何用aspnetpager的url分页方式对datagrid进行分页(使用access数据库):
  /// <code><![cdata[
  ///<%@register tagprefix="webdiyer" namespace="wuqi.webdiyer" assembly="aspnetpager"%>
  ///<%@import namespace="system.data.oledb"%>
  ///<%@ import namespace="system.data"%>
  ///<%@ page language="c#" debug=true%>
  ///<html>
  /// <head>
  ///  <title>welcome to webdiyer.com </title>
  ///  <script runat="server">
  ///  oledbconnection conn;
  ///  oledbcommand cmd;
  ///  void page_load(object src,eventargs e){
  ///  conn=new oledbconnection("provider=microsoft.jet.oledb.4.0;data source="+server.mappath("access/aspnetpager.mdb"));
  ///  if(!page.ispostback){
  ///  cmd=new oledbcommand("select count(newsid) from wqnews",conn);
  ///  conn.open();
  ///  pager.recordcount=(int)cmd.executescalar();
  ///  conn.close();
  ///  binddata();
  ///  }
  ///  }
  ///
  ///  void binddata(){
  ///  cmd=new oledbcommand("select newsid,heading,source,addtime from wqnews order by addtime desc",conn);
  ///  oledbdataadapter adapter=new oledbdataadapter(cmd);
  ///  dataset ds=new dataset();
  ///  adapter.fill(ds,pager.pagesize*(pager.currentpageindex-1),pager.pagesize,"news");
  ///  dg.datasource=ds.tables["news"];
  ///  dg.databind();
  ///  }
  ///
  ///  void changepage(object src,pagechangedeventargs e){
  ///  pager.currentpageindex=e.newpageindex;
  ///  binddata();
  ///  }
  ///
  ///  </script>
  ///  <meta http-equiv="content-language" content="zh-cn">
  ///  <meta http-equiv="content-type" content="text/html;charset=gb2312">
  ///  <meta name="generator" content="editplus">
  ///  <meta name="author" content="webdiyer(yhaili@21cn.com)">
  /// </head>
  /// <body>
  ///  <form runat="server" id="form1">
  ///   <h2 align="center">aspnetpager分页示例</h2>
  ///   <asp:datagrid id="dg" runat="server" 
  ///   width="760" cellpadding="4" align="center" />
  ///   
  ///   <webdiyer:aspnetpager runat="server" id="pager" 
  ///   onpagechanged="changepage" 
  ///   horizontalalign="center" 
  ///   style="margin-top:10px;font-size:16px" 
  ///   pagesize="8" 
  ///   showinputbox="always" 
  ///   submitbuttonstyle="border:1px solid #000066;height:20px;width:30px" 
  ///   inputboxstyle="border:1px #0000ff solid;text-align:center" 
  ///   submitbuttontext="转到" 
  ///   urlpaging="true" 
  ///   urlpageindexname="pageindex" />
  ///  </form>
  /// </body>
  ///</html>
  /// ]]></code>
  /// </example>
  [browsable(true),
  category("分页"),
  defaultvalue(false),
  description("是否使用url传递分页信息的方式来分页")]
  public bool urlpaging
  {
   get
   {
    return urlpaging;
   }
   set
   {
    urlpaging=value;
   }
  }

  /// <summary>
  /// 获取或设置当启用url分页方式时,在url中表示要传递的页索引的参数的名称。
  /// </summary>
  /// <remarks>
  /// 该属性允许您自定义通过url传递页索引时表示要传递的页索引的参数的名称,以避免与现有的参数名重复。
  /// <p>该属性的默认值是“page”,即通过url分页时,显示在浏览器地址栏中的url类似于:</p>http://www.webdiyer.com/aspnetpager/samples/datagrid_url.aspx?page=2 
  /// <p>如将该值改为“pageindex”,则上面的url将变为:</p><p>http://www.webdiyer.com/aspnetpager/samples/datagrid_url.aspx?pageindex=2 </p>
  /// </remarks>
  [browsable(true),
  defaultvalue("page"),
  category("分页"),
  description("当启用url分页方式时,显示在url中表示要传递的页索引的参数的名称")]
  public string urlpageindexname
  {
   get{return urlpageindexname;}
   set{urlpageindexname=value;}
  }

  /// <summary>
  /// 获取或设置当前显示页的索引。
  /// </summary>
  ///<remarks>使用此属性来确定在 aspnetpager 控件中当前显示的页,当前显示的页的数字索引将以红色字体加粗显示。此属性还用于以编程的方式控制所显示的页。
  ///<p> <b>注意:</b>不同于datagrid控件的currentpageindex,aspnetpager的currentpageindex属性是从1开始的。</p></remarks>
  [readonly(true),
  browsable(false),
  description("当前显示页的索引"),
  category("分页"),
  defaultvalue(1),
  designerserializationvisibility(designerserializationvisibility.hidden)]
  public int  currentpageindex
  {
   get
   {
    object cpage=viewstate["currentpageindex"];
    int pindex=(cpage==null)?1:(int)cpage;
    if(pindex>pagecount&&pagecount>0)
     return pagecount;
    else if(pindex<1)
     return 1;
    return pindex;
   }
   set
   {
    int cpage=value;
    if(cpage<1)
     cpage=1;
    else if(cpage>this.pagecount)
     cpage=this.pagecount;
    viewstate["currentpageindex"]=cpage;
   }
  }

  /// <summary>
  /// 获取或设置需要分页的所有记录的总数。
  /// </summary>
  /// <remarks>
  /// 当页面第一次加载时,应以编程方式将从存储过程或sql语句中返回的数据表中所有要分页的记录的总数赋予该属性,aspnetpager会将其保存的viewstate中并在页面回发时从viewstate中获取该值,因此避免了每次分页都要访问数据库而影响分页性能。aspnetpager根据要分页的所有数据的总项数和 <see cref="pagesize"/> 属性来计算显示所有数据需要的总页数,即 <see cref="pagecount"/>的值。
  /// </remarks>
  /// <example>
  /// 下面的示例显示如何以编程方式将从sql语句返回的记录总数赋给该属性:
  /// <p>
  /// <code><![cdata[
  /// <html>
  /// <head>
  /// <title>welcome to webdiyer.com </title>
  /// <script runat="server">
  ///  sqlconnection conn;
  ///  sqlcommand cmd;
  ///  void page_load(object src,eventargs e)
  ///  {
  ///   conn=new sqlconnection(configurationsettings.appsettings["connstr"]);
  ///   if(!page.ispostback)
  ///   {
  ///    cmd=new sqlcommand("select count(id) from news",conn);
  ///    conn.open();
  ///    pager.recordcount=(int)cmd.executescalar();
  ///    conn.close();
  ///    binddata();
  ///   }
  ///  }
  ///
  ///  void binddata()
  ///  {
  ///   cmd=new sqlcommand("getpagednews",conn);
  ///   cmd.commandtype=commandtype.storedprocedure;
  ///   cmd.parameters.add("@pageindex",pager.currentpageindex);
  ///   cmd.parameters.add("@pagesize",pager.pagesize);
  ///   conn.open();
  ///   datagrid1.datasource=cmd.executereader();
  ///   datagrid1.databind();
  ///   conn.close();
  ///  }
  ///  void changepage(object src,pagechangedeventargs e)
  ///  {
  ///   pager.currentpageindex=e.newpageindex;
  ///   binddata();
  ///  }
  ///  </script>
  ///  <meta http-equiv="content-language" content="zh-cn">
  ///  <meta http-equiv="content-type" content="text/html;charset=gb2312">
  ///  <meta name="generator" content="editplus">
  ///  <meta name="author" content="webdiyer(yhaili@21cn.com)">
  /// </head>
  /// <body>
  ///  <form runat="server" id="form1">
  ///   <asp:datagrid id="datagrid1" runat="server" />
  ///
  ///   <webdiyer:aspnetpager id="pager" runat="server" 
  ///   pagesize="8" 
  ///   numericbuttoncount="8" 
  ///   showcustominfosection="before" 
  ///   showinputbox="always" 
  ///   cssclass="mypager" 
  ///   horizontalalign="center" 
  ///   onpagechanged="changepage" />
  ///
  ///  </form>
  /// </body>
  ///</html>
  /// ]]>
  /// </code></p>
  /// <p>本示例使用的存储过程代码如下:</p>
  /// <code><![cdata[
  ///create procedure getpagednews
  ///  (@pagesize int,
  ///  @pageindex int)
  ///  as
  ///  set nocount on
  ///  declare @indextable table(id int identity(1,1),nid int)
  ///  declare @pagelowerbound int
  ///  declare @pageupperbound int
  ///  set @pagelowerbound=(@pageindex-1)*@pagesize
  ///  set @pageupperbound=@pagelowerbound+@pagesize
  ///  set rowcount @pageupperbound
  ///  insert into @indextable(nid) select id from news order by addtime desc
  ///  select o.id,o.title,o.source,o.addtime from news o,@indextable t where o.id=t.nid
  ///  and t.id>@pagelowerbound and t.id<=@pageupperbound order by t.id
  ///  set nocount off
  ///go
  /// ]]>
  /// </code>
  /// </example>
  [browsable(false),
  description("要分页的所有记录的总数,该值须在程序运行时设置,默认值为225是为设计时支持而设置的参照值。"),
  category("data"),
  defaultvalue(225)]
  public int recordcount
  {
   get
   {
    object obj=viewstate["recordcount"];
    return (obj==null)?0:(int)obj;
   }
   set{viewstate["recordcount"]=value;}
  }

  /// <summary>
  /// 获取当前页之后未显示的页的总数。
  /// </summary>
  [browsable(false),
  designerserializationvisibility(designerserializationvisibility.hidden)]
  public int pagesremain
  {
   get
   {
    return pagecount-currentpageindex;
   }
  }

  /// <summary>
  /// 获取或设置每页显示的项数。
  /// </summary>
  /// <remarks>
  /// 该值获取或设置数据呈现控件每次要显示数据表中的的数据的项数,aspnetpager根据该值和 <see cref="recordcount"/> 来计算显示所有数据需要的总页数,即 <see cref="pagecount"/>的值。</remarks>
  /// <example>以下示例将 <see cref="aspnetpager"/> 设置为允许每页显示8条数据:
  /// <code>
  /// <![cdata[
  ///  ...
  ///  <webdiyer:aspnetpager id="pager" runat="server" pagesize=8 onpagechanged="changepage"/>
  ///  ...
  /// ]]></code></example>
  [browsable(true),
  description("每页显示的记录数"),
  category("分页"),
  defaultvalue(10)]
  public int pagesize
  {
   get
   {
    object obj=viewstate["pagesize"];
    return (obj==null)?10:(int)obj;
   }
   set
   {
    viewstate["pagesize"]=value;
   }
  }

  /// <summary>
  /// 获取在当前页之后还未显示的剩余记录的项数。
  /// </summary>
  [browsable(false),
  designerserializationvisibility(designerserializationvisibility.hidden)]
  public int recordsremain
  {
   get
   {
    if(currentpageindex<pagecount)
     return recordcount-(currentpageindex*pagesize);
    return 0;}
  }


  /// <summary>
  /// 获取所有要分页的记录需要的总页数。
  /// </summary>
  [browsable(false),
  designerserializationvisibility(designerserializationvisibility.hidden)]
  public int pagecount
  {
   get{return (int)math.ceiling((double)recordcount/(double)pagesize);}
  }

  
  #endregion

  #region textbox and submit button

  /// <summary>
  /// 获取或设置页索引文本框的显示方式。
  /// </summary>
  /// <remarks>
  /// 页索引文件框允许用户手式输入要访问的页的索引,当页数非常多时,显示页索引文本框非常方便用户跳转到指定的页,默认情况下,该文本框只有在总页数大于或等于 <see cref="showboxthreshold"/> 的值时才显示,否则不显示,要想该文本框任何时候都显示,请将其值设为always,若希望任何时候都不显示,则应设为never。
  ///</remarks>
  [browsable(true),
  description("指定页索引文本框的显示方式"),
  category("文本框及提交按钮"),
  defaultvalue(showinputbox.auto)]
  public showinputbox showinputbox
  {
   get
   {
    object obj=viewstate["showinputbox"];
    return (obj==null)?showinputbox.auto:(showinputbox)obj;
   }
   set{viewstate["showinputbox"]=value;}
  }

  /// <summary>
  /// 获取或设置应用于页索引输入文本框的css类名。
  /// </summary>
  [browsable(true),
  category("文本框及提交按钮"),
  defaultvalue(null),
  description("应用于页索引输入文本框的css类名")]
  public string inputboxclass
  {
   get
   {
    return (string)viewstate["inpubboxclass"];
   }
   set
   {
    if(value.trim().length>0)
     viewstate["inputboxclass"]=value;
   }
  }

  /// <summary>
  /// 获取或设置页索引输入文本框的css样式文本。
  /// </summary>

  [browsable(true),
  category("文本框及提交按钮"),
  defaultvalue(null),
  description("应用于页索引输入文本框的css样式文本")]
  public string inputboxstyle
  {
   get
   {
    return (string)viewstate["inputboxstyle"];
   }
   set
   {
    if(value.trim().length>0)
     viewstate["inputboxstyle"]=value;
   }
  }

  /// <summary>
  /// 获取或设置页索引页索引输入文本框前的文本字符串值。
  /// </summary>
  [browsable(true),
  category("文本框及提交按钮"),
  defaultvalue(null),
  description("页索引输入文本框前的文本内容字符串")]
  public string textbeforeinputbox
  {
   get
   {
    return (string)viewstate["textbeforeinputbox"];
   }
   set
   {
    viewstate["textbeforeinputbox"]=value;
   }
  }

  /// <summary>
  /// 获取或设置页索引文本输入框后的文本内容字符串值。
  /// </summary>
  [browsable(true),
  defaultvalue(null),
  category("文本框及提交按钮"),
  description("页索引输入文本框后的文本内容字符串")]
  public string textafterinputbox
  {
   get
   {
    return (string)viewstate["textafterinputbox"];
   }
   set
   {
    viewstate["textafterinputbox"]=value;
   }
  }


  /// <summary>
  /// 获取或设置提交按钮上的文本。
  /// </summary>
  [browsable(true),
  category("文本框及提交按钮"),
  defaultvalue("go"),
  description("提交按钮上的文本")]
  public string submitbuttontext
  {
   get
   {
    object obj=viewstate["submitbuttontext"];
    return (obj==null)?"go":(string)obj;
   }
   set
   {
    if(value.trim().length>0)
     viewstate["submitbuttontext"]=value;
   }
  }
  /// <summary>
  /// 获取或设置应用于提交按钮的css类名。
  /// </summary>
  [browsable(true),
  category("文本框及提交按钮"),
  defaultvalue(null),
  description("应用于提交按钮的css类名")]
  public string submitbuttonclass
  {
   get
   {
    return (string)viewstate["submitbuttonclass"];
   }
   set
   {
    viewstate["submitbuttonclass"]=value;
   }
  }

  /// <summary>
  /// 获取或设置应用于提交按钮的css样式。
  /// </summary>
  [browsable(true),
  category("文本框及提交按钮"),
  defaultvalue(null),
  description("应用于提交按钮的css样式")]
  public string submitbuttonstyle
  {
   get
   {
    return (string)viewstate["submitbuttonstyle"];
   }
   set
   {
    viewstate["submitbuttonstyle"]=value;
   }
  }
  /// <summary>
  /// 获取或设置自动显示页索引输入文本框的最低起始页数。
  /// </summary>
  /// <remarks>
  /// 当 <see cref="showinputbox"/> 设为auto(默认)并且要分页的数据的总页数达到该值时会自动显示页索引输入文本框,默认值为30。该选项当 <see cref="showinputbox"/> 设为never或always时没有任何作用。
  /// </remarks>
  [browsable(true),
  description("指定当showinputbox设为showinputbox.auto时,当总页数达到多少时才显示页索引输入文本框"),
  category("文本框及提交按钮"),
  defaultvalue(30)]
  public int showboxthreshold
  {
   get
   {
    object obj=viewstate["showboxthreshold"];
    return (obj==null)?30:(int)obj;
   }
   set{viewstate["showboxthreshold"]=value;}
  }


  #endregion

  #region custominfosection

  /// <summary>
  /// 获取或设置显示用户自定义信息区的方式。
  /// </summary>
  /// <remarks>
  /// 该属性值设为left或right时会在分页导航元素左边或右边划出一个专门的区域来显示有关用户自定义信息,设为never时不显示。
  /// </remarks>
  [browsable(true),
  description("显示当前页和总页数信息,默认值为不显示,值为showcustominfosection.left时将显示在页索引前,为showcustominfosection.right时将显示在页索引后"),
  defaultvalue(showcustominfosection.never),
  category("自定义信息区")]
  public showcustominfosection showcustominfosection
  {
   get
   {
    object obj=viewstate["showcustominfosection"];
    return (obj==null)?showcustominfosection.never:(showcustominfosection)obj;
   }
   set{viewstate["showcustominfosection"]=value;}
  }

  /// <summary>
  /// 获取或设置用户自定义信息区文本的对齐方式。
  /// </summary>
  [browsable(true),
  category("自定义信息区"),
  defaultvalue(horizontalalign.left),
  description("用户自定义信息区文本的对齐方式")]
  public horizontalalign custominfotextalign
  {
   get
   {
    object obj=viewstate["custominfotextalign"];
    return (obj==null)?horizontalalign.left:(horizontalalign)obj;
   }
   set
   {
    viewstate["custominfotextalign"]=value;
   }
  }

  /// <summary>
  /// 获取或设置用户自定义信息区的宽度。
  /// </summary>
  [browsable(true),
  category("自定义信息区"),
  defaultvalue(typeof(unit),"40%"),
  description("用户自定义信息区的宽度")]
  public unit custominfosectionwidth
  {
   get
   {
    object obj=viewstate["custominfosectionwidth"];
    return (obj==null)?unit.percentage(40):(unit)obj;
   }
   set
   {
    viewstate["custominfosectionwidth"]=value;
   }
  }

  /// <summary>
  /// 获取或设置应用于用户自定义信息区的级联样式表类名。
  /// </summary>
  [browsable(true),
  category("自定义信息区"),
  defaultvalue(null),
  description("应用于用户自定义信息区的级联样式表类名")]
  public string custominfoclass
  {
   get
   {
    object obj=viewstate["custominfoclass"];
    return (obj==null)?cssclass:(string)obj;
   }
   set
   {
    viewstate["custominfoclass"]=value;
   }
  }

  /// <summary>
  /// 获取或设置应用于用户自定义信息区的css样式文本。
  /// </summary>
  /// <value>字符串值,要应用于用户自定义信息区的css样式文本。</value>
  [browsable(true),
  category("自定义信息区"),
  defaultvalue(null),
  description("应用于用户自定义信息区的css样式文本")]
  public string custominfostyle
  {
   get
   {
    object obj=viewstate["custominfostyle"];
    return (obj==null)?getstylestring():(string)obj;
   }
   set
   {
    viewstate["custominfostyle"]=value;
   }
  }

  /// <summary>
  /// 获取或设置在显示在用户自定义信息区的用户自定义文本。
  /// </summary>
  [browsable(true),
  category("自定义信息区"),
  defaultvalue(null),
  description("要显示在用户自定义信息区的用户自定义信息文本")]
  public string custominfotext
  {
   get
   {
    return (string)viewstate["custominfotext"];
   }
   set
   {
    viewstate["custominfotext"]=value;
   }
  }

  #endregion

  #region others

  /// <summary>
  /// 获取或设置一个值,该值指定是否总是显示aspnetpager分页按件,即使要分页的数据只有一页。
  /// </summary>
  /// <remarks>
  /// 默认情况下,当要分页的数据小于两页时,aspnetpager不会在页面上显示任何内容,将此属性值设为true时,即使总页数只有一页,aspnetpager也将显示分页导航元素。
  /// </remarks>
  [browsable(true),
  category("behavior"),
  defaultvalue(false),
  description("总是显示分页控件,即使要分页的数据只要一页")]
  public bool alwaysshow
  {
   get
   {
    object obj=viewstate["alwaysshow"];
    return (obj==null)?false:(bool)obj;
   }
   set
   {
    viewstate["alwaysshow"]=value;
   }
  }


  /// <summary>
  /// 获取或设置由 aspnetpager 服务器控件在客户端呈现的级联样式表 (css) 类。
  /// </summary>
  [browsable(true),
  description("应用于控件的css类名"),
  category("appearance"),
  defaultvalue(null)]
  public override string cssclass
  {
   get{return base.cssclass;}
   set
   {
    base.cssclass=value;
    cssclassname=value;
   }
  }


  /// <summary>
  /// 获取或设置一个值,该值指示 aspnetpager 服务器控件是否向发出请求的客户端保持自己的视图状态,该属性经重写后不允许设为false。
  /// </summary>
  /// <remarks><see cref="aspnetpager"/> 服务器控件将一些重要的分页信息保存在viewstate中,当使用url分页方式时,虽然视图状态在分页过程中没有任何作用,但若当前页需要回发,则必须启用视图状态以便分页控件能在页面回发后获取回发前的分页状态;当通过页面回发(postback)的方式来分页时,要使aspnetpager正常工作,必须启用视图状态。
  /// <p><note>该属性并不能禁止用户用<![cdata[<%@page enableviewstate=false%> ]]>页指令来禁用整个页面的视图状态,当使用此指令并且设置aspnetpager通过页面回发来分页时,aspnetpager因为无法获取保存的信息而不能正常工作。</note></p></remarks>
  [browsable(false),
  description("是否启用控件的视图状态,该属性的值必须为true,不允许用户设置。"),
  defaultvalue(true),
  category("behavior")]
  public override bool enableviewstate
  {
   get
   {
    return base.enableviewstate;
   }
   set
   {
    base.enableviewstate=true;
   }
  }

 

  #endregion

  #endregion

  #region control rendering logic

  /// <summary>
  /// 重写 <see cref="system.web.ui.control.onload"/> 方法。
  /// </summary>
  /// <param name="e">包含事件数据的 <see cref="eventargs"/> 对象。</param>
  protected override void onload(eventargs e)
  {
   if(urlpaging)
   {
    currenturl=page.request.path;
    urlparams=page.request.querystring;
    string pageindex=page.request.querystring[urlpageindexname];
    int index=1;
    try
    {
     index=int.parse(pageindex);
    }
    catch{}
    onpagechanged(new pagechangedeventargs(index));
   }
   else
   {
    inputpageindex=page.request.form[this.uniqueid+"_input"];
   }
   base.onload(e);
  }
  /// <summary>
  /// 重写<see cref="system.web.ui.control.onprerender"/>方法。
  /// </summary>
  /// <param name="e">包含事件数据的 <see cref="eventargs"/> 对象。</param>
  protected override void onprerender(eventargs e)
  {
   if(pagecount>1)
   {
    string checkscript="<script language=\"javascript\">function docheck(el){var r=new regexp(\"^\\\\s*(\\\\d+)\\\\s*$\");if(r.test(el.value)){if(regexp.$1<1||regexp.$1>"+pagecount.tostring()+"){alert(\"页数必须介于1和"+pagecount.tostring()+"之间!\");document.all[\'"+this.uniqueid+"_input\'].select();return false;}return true;}alert(\"输入的页索引无效!\");document.all[\'"+this.uniqueid+"_input\'].select();return false;}</script>";
    if((showinputbox==showinputbox.always)||(showinputbox==showinputbox.auto&&pagecount>=showboxthreshold))
    {
     if(!page.isclientscriptblockregistered("checkinput"))
      page.registerclientscriptblock("checkinput",checkscript);
     string script="<script language=\"javascript\" > <!-- \nfunction buildurlstring(key,value){ var loc=window.location.search.substring(1); var params=loc.split(\"&\"); if(params.length<=1||(params.length==2&&params[0].tolowercase()==key)) return location.pathname+\"?\"+key+\"=\"+value; var newparam=\"\"; var flag=false; for(i=0;i<params.length;i++){ if(params[i].split(\"=\")[0].tolowercase()==key.tolowercase()){ params[i]=key+\"=\"+value; flag=true; break; } } for(i=0;i<params.length;i++){ newparam+=params[i]+\"&\"; } if(flag) newparam=newparam.substring(0,newparam.length-1); else newparam+=key+\"=\"+value; return location.pathname+\"?\"+newparam; } \n//--> </script>";
     if(!page.isclientscriptblockregistered("buildurlscript"))
      page.registerclientscriptblock("buildurlscript",script);
    }
   }
   base.onprerender(e);
  }

  ///<summary>
  ///重写 <see cref="system.web.ui.webcontrols.webcontrol.renderbegintag"/> 方法,将 <see cref="aspnetpager"/> 控件的 html 开始标记输出到指定的 <see cref="system.web.ui.htmltextwriter"/> 编写器中。
  ///</summary>
  ///<param name="writer"><see cref="system.web.ui.htmltextwriter"/>,表示要在客户端呈现 html 内容的输出流。</param>
  public override void renderbegintag(htmltextwriter writer)
  {
   bool showpager=(pagecount>1||(pagecount<=1&&alwaysshow));
   writer.writeline();
   writer.write("<!------------------------------ ");
   writer.write("aspnetpager v4.2 start");
   writer.writeline(" ------------------------------>");
   writer.write("<!-------------------- ");
   writer.write("copyright:2003 webdiyer(www.webdiyer.com)");
   writer.write(" ---------------------");
   writer.writeline(">");
   base.renderbegintag(writer);
   if(!showpager)
   {
    writer.write("<!-----因为总页数只有一页,并且alwaysshow属性设为false,aspnetpager没有显示任何内容,若要在总页数只有一页的情况下显示aspnetpager,请将alwaysshow属性设为true!");
    writer.write("----->");
   }
   if((showcustominfosection==showcustominfosection.left||showcustominfosection==showcustominfosection.right)&&showpager)
   {
    writer.addattribute(htmltextwriterattribute.width,"100%");
    writer.addattribute(htmltextwriterattribute.style,getstylestring());
    if(height!=unit.empty)
     writer.addstyleattribute(htmltextwriterstyle.height,height.tostring());
    writer.addattribute(htmltextwriterattribute.border,"0");
    writer.addattribute(htmltextwriterattribute.cellpadding,"0");
    writer.addattribute(htmltextwriterattribute.cellspacing,"0");
    writer.renderbegintag(htmltextwritertag.table);
    writer.renderbegintag(htmltextwritertag.tr);
    writecellattributes(writer,true);
    writer.renderbegintag(htmltextwritertag.td);
   }
  }

  ///<summary>
  ///重写 <see cref="system.web.ui.webcontrols.webcontrol.renderendtag"/> 方法,将 <see cref="aspnetpager"/> 控件的 html 结束标记输出到指定的 <see cref="system.web.ui.htmltextwriter"/> 编写器中。
  ///</summary>
  ///<param name="writer"><see cref="system.web.ui.htmltextwriter"/>,表示要在客户端呈现 html 内容的输出流。</param>

  public override void renderendtag(htmltextwriter writer)
  {
   if((showcustominfosection==showcustominfosection.left||showcustominfosection==showcustominfosection.right)&&pagecount>1)
   {
    writer.renderendtag();
    writer.renderendtag();
    writer.renderendtag();
   }
   base.renderendtag(writer);
   writer.writeline();
   writer.write("<!------------------------------- ");
   writer.write("aspnetpager v4.2 end");
   writer.write(" --------------------------------");
   writer.writeline(">");
   writer.writeline();
  }

  
  /// <summary>
  /// 重写 <see cref="system.web.ui.webcontrols.webcontrol.rendercontents"/> 方法,将控件的内容呈现到指定 <see cref="system.web.ui.htmltextwriter"/> 的编写器中。
  /// </summary>
  /// <param name="writer"><see cref="system.web.ui.htmltextwriter"/>,表示要在客户端呈现 html 内容的输出流。</param>
  protected override void rendercontents(htmltextwriter writer)
  {
   if(pagecount<=1&&!alwaysshow)
    return;

   if(showcustominfosection==showcustominfosection.left)
   {
    writer.write(custominfotext);
    writer.renderendtag();
    writecellattributes(writer,false);
    writer.addattribute(htmltextwriterattribute.class,cssclass);
    writer.renderbegintag(htmltextwritertag.td);
   }

   int midpage=(int)((currentpageindex-1)/numericbuttoncount);
   int pageoffset=midpage*numericbuttoncount;
   int endpage=((pageoffset+numericbuttoncount)>pagecount)?pagecount:(pageoffset+numericbuttoncount);
   this.createnavigationbutton(writer,"first");
   this.createnavigationbutton(writer,"prev");
   if(showpageindex)
   {
    if(currentpageindex>numericbuttoncount)
     createmorebutton(writer,pageoffset);
    for(int i=pageoffset+1;i<=endpage;i++)
    {
     createnumericbutton(writer,i);
    }
    if(pagecount>numericbuttoncount&&endpage<pagecount)
     createmorebutton(writer,endpage+1);
   }
   this.createnavigationbutton(writer,"next");
   this.createnavigationbutton(writer,"last");
   if((showinputbox==showinputbox.always)||(showinputbox==showinputbox.auto&&pagecount>=showboxthreshold))
   {
    writer.write("    ");
    if(textbeforeinputbox!=null)
     writer.write(textbeforeinputbox);
    writer.addattribute(htmltextwriterattribute.type,"text");
    writer.addstyleattribute(htmltextwriterstyle.width,"30px");
    writer.addattribute(htmltextwriterattribute.value,inputpageindex);
    if(inputboxstyle!=null&&inputboxstyle.trim().length>0)
     writer.addattribute(htmltextwriterattribute.style,inputboxstyle);
    if(inputboxclass!=null&&inputboxclass.trim().length>0)
     writer.addattribute(htmltextwriterattribute.class,inputboxclass);
    if(pagecount<=1&&alwaysshow)
     writer.addattribute(htmltextwriterattribute.readonly,"true");
    writer.addattribute(htmltextwriterattribute.name,this.uniqueid+"_input");
    string scriptref="docheck(document.all[\'"+this.uniqueid+"_input\'])";
    string postref="if(event.keycode==13){if("+scriptref+")__dopostback(\'"+this.uniqueid+"\',document.all[\'"+this.uniqueid+"_input\'].value);else{event.returnvalue=false;}}";
    string keydownscript="if(event.keycode==13){if("+scriptref+"){event.returnvalue=false;document.all[\'"+this.uniqueid+"\'][1].click();}else{event.returnvalue=false;}}";
    string clickscript="if("+scriptref+"){location.href=buildurlstring(\'"+urlpageindexname+"\',document.all[\'"+this.uniqueid+"_input\'].value)}";
    writer.addattribute("onkeydown",(urlpaging==true)?keydownscript:postref);
    writer.renderbegintag(htmltextwritertag.input);
    writer.renderendtag();
    if(textafterinputbox!=null)
     writer.write(textafterinputbox);
    writer.addattribute(htmltextwriterattribute.type,(urlpaging==true)?"button":"submit");
    writer.addattribute(htmltextwriterattribute.name,this.uniqueid);
    writer.addattribute(htmltextwriterattribute.value,submitbuttontext);
    if(submitbuttonclass!=null&&submitbuttonclass.trim().length>0)
     writer.addattribute(htmltextwriterattribute.class,submitbuttonclass);
    if(submitbuttonstyle!=null&&submitbuttonstyle.trim().length>0)
     writer.addattribute(htmltextwriterattribute.style,submitbuttonstyle);
    if(pagecount<=1&&alwaysshow)
     writer.addattribute(htmltextwriterattribute.disabled,"true");
    writer.addattribute(htmltextwriterattribute.onclick,(urlpaging==true)?clickscript:"return "+scriptref);
    writer.renderbegintag(htmltextwritertag.input);
    writer.renderendtag();}

   if(showcustominfosection==showcustominfosection.right)
   {
    writer.renderendtag();
    writecellattributes(writer,false);
    writer.renderbegintag(htmltextwritertag.td);
    writer.write(custominfotext);
   }
  }


  #endregion

  #region private helper functions

  /// <summary>
  /// 将基控件的style转换为css字符串。
  /// </summary>
  /// <returns></returns>
  private string getstylestring()
  {
   if(style.count>0)
   {
    string stl=null;
    string[] skeys=new string[style.count];
    style.keys.copyto(skeys,0);
    for(int i=0;i<skeys.length;i++)
    {
     stl+=string.concat(skeys[i],":",style[skeys[i]],";");
    }
    return stl;
   }
   return null;
  }

  /// <summary>
  /// 为用户自定义信息区和页导航按钮区和td添加属性。
  /// </summary>
  /// <param name="writer"></param>
  /// <param name="leftcell">是否为第一个td</param>
  private void writecellattributes(htmltextwriter writer,bool leftcell)
  {
   string customunit=custominfosectionwidth.tostring();
   if(showcustominfosection==showcustominfosection.left&&leftcell||showcustominfosection==showcustominfosection.right&&!leftcell)
   {
    if(custominfoclass!=null&&custominfoclass.trim().length>0)
     writer.addattribute(htmltextwriterattribute.class,custominfoclass);
    if(custominfostyle!=null&&custominfostyle.trim().length>0)
     writer.addattribute(htmltextwriterattribute.style,custominfostyle);
    writer.addattribute(htmltextwriterattribute.valign,"bottom");
    writer.addstyleattribute(htmltextwriterstyle.width,customunit);
    writer.addattribute(htmltextwriterattribute.align,custominfotextalign.tostring().tolower());
   }
   else
   {
    if(custominfosectionwidth.type==unittype.percentage)
    {
     customunit=(unit.percentage(100-custominfosectionwidth.value)).tostring();
     writer.addstyleattribute(htmltextwriterstyle.width,customunit);
    }
    writer.addattribute(htmltextwriterattribute.valign,"bottom");
    writer.addattribute(htmltextwriterattribute.align,horizontalalign.tostring().tolower());
   }
   writer.addattribute(htmltextwriterattribute.nowrap,"true");
  }

  /// <summary>
  /// 获取分页导航按钮的超链接字符串。
  /// </summary>
  /// <param name="pageindex">该分页按钮相对应的页索引。</param>
  /// <returns>分页导航按钮的超链接字符串。</returns>
  private string gethrefstring(int pageindex)
  {
   if(urlpaging)
   {
    namevaluecollection col=new namevaluecollection();
    col.add(urlpageindexname,pageindex.tostring());
    return buildurlstring(col);
   }
   return page.getpostbackclienthyperlink(this,pageindex.tostring());
  }

  /// <summary>
  /// 当使用url分页方式时,在当前url上加入分页参数,若该参数存在,则改变其值。
  /// </summary>
  /// <param name="col">要加入到新url中的参数名和值的集合。</param>
  /// <returns>分页导航按钮的超链接字符串,包括分页参数。</returns>
  private string buildurlstring(namevaluecollection col)
  {
   int i;
   string tempstr="";
   if(urlparams==null||urlparams.count<=0)
   {
    for(i=0;i<col.count;i++)
    {
     tempstr+=string.concat("&",col.keys[i],"=",col[i]);
    }
    return string.concat(currenturl,"?",tempstr.substring(1));
   }
   namevaluecollection newcol=new namevaluecollection(urlparams);
   string[] newcolkeys=newcol.allkeys;
   for(i=0;i<newcolkeys.length;i++)
   {
    newcolkeys[i]=newcolkeys[i].tolower();
   }
   for(i=0;i<col.count;i++)
   {
    if(array.indexof(newcolkeys,col.keys[i].tolower())<0)
     newcol.add(col.keys[i],col[i]);
    else
     newcol[col.keys[i]]=col[i];
   }
   system.text.stringbuilder sb=new system.text.stringbuilder();
   for(i=0;i<newcol.count;i++)
   {
    sb.append("&");
    sb.append(newcol.keys[i]);
    sb.append("=");
    sb.append(newcol[i]);
   }
   return string.concat(currenturl,"?",sb.tostring().substring(1));
  }

  /// <summary>
  /// 创建第一页、上一页、下一页及最后一页分页按钮。
  /// </summary>
  /// <param name="writer"><see cref="system.web.ui.htmltextwriter"/>,表示要在客户端呈现 html 内容的输出流。</param>
  /// <param name="btnname">分页按钮名。</param>
  private void createnavigationbutton(htmltextwriter writer,string btnname)
  {
   if(!showfirstlast&&(btnname=="first"||btnname=="last"))
    return;
   if(!showprevnext&&(btnname=="prev"||btnname=="next"))
    return;
   string linktext="";
   bool disabled;
   int pageindex;
   bool imgbutton=(pagingbuttontype==pagingbuttontype.image&&navigationbuttontype==pagingbuttontype.image);
   if(btnname=="prev"||btnname=="first")
   {
    disabled=(currentpageindex<=1);
    if(!showdisabledbuttons&&disabled)
     return;
    pageindex=(btnname=="first")?1:(currentpageindex-1);
    if(imgbutton)
    {
     if(!disabled)
     {
      writer.addattribute(htmltextwriterattribute.href,gethrefstring(pageindex));
      addtooltip(writer,pageindex);
      writer.renderbegintag(htmltextwritertag.a);
      writer.addattribute(htmltextwriterattribute.src,string.concat(imagepath,btnname,buttonimagenameextension,buttonimageextension));
      writer.addattribute(htmltextwriterattribute.border,"0");
      writer.addattribute(htmltextwriterattribute.align,buttonimagealign.tostring());
      writer.renderbegintag(htmltextwritertag.img);
      writer.renderendtag();
      writer.renderendtag();
     }
     else
     {
      writer.addattribute(htmltextwriterattribute.src,string.concat(imagepath,btnname,disabledbuttonimagenameextension,buttonimageextension));
      writer.addattribute(htmltextwriterattribute.border,"0");
      writer.addattribute(htmltextwriterattribute.align,buttonimagealign.tostring());
      writer.renderbegintag(htmltextwritertag.img);
      writer.renderendtag();
     }
    }
    else
    {
     linktext=(btnname=="prev")?prevpagetext:firstpagetext;
     if(disabled)
      writer.addattribute(htmltextwriterattribute.disabled,"true");
     else
     {
      writecssclass(writer);
      addtooltip(writer,pageindex);
      writer.addattribute(htmltextwriterattribute.href,gethrefstring(pageindex));
     }
     writer.renderbegintag(htmltextwritertag.a);
     writer.write(linktext);
     writer.renderendtag();
    }
   }
   else
   {
    disabled=(currentpageindex>=pagecount);
    if(!showdisabledbuttons&&disabled)
     return;
    pageindex=(btnname=="last")?pagecount:(currentpageindex+1);
    if(imgbutton)
    {
     if(!disabled)
     {
      writer.addattribute(htmltextwriterattribute.href,gethrefstring(pageindex));
      addtooltip(writer,pageindex);
      writer.renderbegintag(htmltextwritertag.a);
      writer.addattribute(htmltextwriterattribute.src,string.concat(imagepath,btnname,buttonimagenameextension,buttonimageextension));
      writer.addattribute(htmltextwriterattribute.border,"0");
      writer.addattribute(htmltextwriterattribute.align,buttonimagealign.tostring());
      writer.renderbegintag(htmltextwritertag.img);
      writer.renderendtag();
      writer.renderendtag();
     }
     else
     {
      writer.addattribute(htmltextwriterattribute.src,string.concat(imagepath,btnname,disabledbuttonimagenameextension,buttonimageextension));
      writer.addattribute(htmltextwriterattribute.border,"0");
      writer.addattribute(htmltextwriterattribute.align,buttonimagealign.tostring());
      writer.renderbegintag(htmltextwritertag.img);
      writer.renderendtag();
     }
    }
    else
    {
     linktext=(btnname=="next")?nextpagetext:lastpagetext;
     if(disabled)
      writer.addattribute(htmltextwriterattribute.disabled,"true");
     else
     {
      writecssclass(writer);
      addtooltip(writer,pageindex);
      writer.addattribute(htmltextwriterattribute.href,gethrefstring(pageindex));
     }
     writer.renderbegintag(htmltextwritertag.a);
     writer.write(linktext);
     writer.renderendtag();
    }
   }
   writebuttonspace(writer);
  }

  /// <summary>
  /// 写入css类名。
  /// </summary>
  /// <param name="writer"><see cref="system.web.ui.htmltextwriter"/>,表示要在客户端呈现 html 内容的输出流。</param>
  private void writecssclass(htmltextwriter writer)
  {
   if(cssclassname!=null&&cssclassname.trim().length>0)
    writer.addattribute(htmltextwriterattribute.class,cssclassname);
  }

  /// <summary>
  /// 加入导航按钮提示文本。
  /// </summary>
  /// <param name="writer"><see cref="system.web.ui.htmltextwriter"/>,表示要在客户端呈现 html 内容的输出流。</param>
  /// <param name="pageindex">导航按钮对应的页索引。</param>
  private void addtooltip(htmltextwriter writer,int pageindex)
  {
   if(shownavigationtooltip)
   {
    writer.addattribute(htmltextwriterattribute.title,string.format(navigationtooltiptextformatstring,pageindex));
   }
  }

  /// <summary>
  /// 创建分页数值导航按钮。
  /// </summary>
  /// <param name="writer"><see cref="system.web.ui.htmltextwriter"/>,表示要在客户端呈现 html 内容的输出流。</param>
  /// <param name="index">要创建按钮的页索引的值。</param>
  private void createnumericbutton(htmltextwriter writer,int index)
  {
   bool iscurrent=(index==currentpageindex);
   if(pagingbuttontype==pagingbuttontype.image&&numericbuttontype==pagingbuttontype.image)
   {
    if(!iscurrent)
    {
     writer.addattribute(htmltextwriterattribute.href,gethrefstring(index));
     addtooltip(writer,index);
     writer.renderbegintag(htmltextwritertag.a);
     createnumericimages(writer,index,iscurrent);
     writer.renderendtag();
    }
    else
     createnumericimages(writer,index,iscurrent);
   }
   else
   {
    if(iscurrent)
    {
     writer.addstyleattribute(htmltextwriterstyle.fontweight,"bold");
     writer.addstyleattribute(htmltextwriterstyle.color,"red");
     writer.renderbegintag(htmltextwritertag.font);
     if(numericbuttontextformatstring.length>0)
      writer.write(string.format(numericbuttontextformatstring,(chinesepageindex==true)?getchinesepageindex(index):(index.tostring())));
     else
      writer.write((chinesepageindex==true)?getchinesepageindex(index):index.tostring());
     writer.renderendtag();
    }
    else
    {
     writecssclass(writer);
     addtooltip(writer,index);
     writer.addattribute(htmltextwriterattribute.href,gethrefstring(index));
     writer.renderbegintag(htmltextwritertag.a);
     if(numericbuttontextformatstring.length>0)
      writer.write(string.format(numericbuttontextformatstring,(chinesepageindex==true)?getchinesepageindex(index):(index.tostring())));
     else
      writer.write((chinesepageindex==true)?getchinesepageindex(index):index.tostring());
     writer.renderendtag();
    }
   }
   writebuttonspace(writer);
  }

  /// <summary>
  /// 在分页导航元素间加入空格。
  /// </summary>
  /// <param name="writer"></param>
  private void writebuttonspace(htmltextwriter writer)
  {
   if(pagingbuttonspacing.value>0)
   {
    writer.addstyleattribute(htmltextwriterstyle.width,pagingbuttonspacing.tostring());
    writer.renderbegintag(htmltextwritertag.span);
    writer.renderendtag();
   }
  }

  /// <summary>
  /// 获取中文页索引字符。
  /// </summary>
  /// <param name="index">中文字符对应的页索引数值</param>
  /// <returns>对应于页索引数值的中文字符</returns>
  private string getchinesepageindex(int index)
  {
   hashtable cnchars=new hashtable();
   cnchars.add("0","o");
   cnchars.add("1","一");
   cnchars.add("2","二");
   cnchars.add("3","三");
   cnchars.add("4","四");
   cnchars.add("5","五");
   cnchars.add("6","六");
   cnchars.add("7","七");
   cnchars.add("8","八");
   cnchars.add("9","九");
   string indexstr=index.tostring();
   string retstr="";
   for(int i=0;i<indexstr.length;i++)
   {
    retstr=string.concat(retstr,cnchars[indexstr[i].tostring()]);
   }
   return retstr;
  }

  /// <summary>
  /// 创建页索引图片按钮。
  /// </summary>
  /// <param name="writer"><see cref="system.web.ui.htmltextwriter"/>,表示要在客户端呈现 html 内容的输出流。</param>
  /// <param name="index">页索引数值。</param>
  /// <param name="iscurrent">是否是当前页索引。</param>
  private void createnumericimages(htmltextwriter writer,int index,bool iscurrent)
  {
   string indexstr=index.tostring();
   for(int i=0;i<indexstr.length;i++)
   {
    writer.addattribute(htmltextwriterattribute.src,string.concat(imagepath,indexstr[i],(iscurrent==true)?cpibuttonimagenameextension:buttonimagenameextension,buttonimageextension));
    writer.addattribute(htmltextwriterattribute.align,buttonimagealign.tostring());
    writer.addattribute(htmltextwriterattribute.border,"0");
    writer.renderbegintag(htmltextwritertag.img);
    writer.renderendtag();
   }
  }

  /// <summary>
  /// 创建“更多页”(...)按钮。
  /// </summary>
  /// <param name="writer"><see cref="system.web.ui.htmltextwriter"/>,表示要在客户端呈现 html 内容的输出流。</param>
  /// <param name="pageindex">链接到按钮的页的索引。</param>
  private void createmorebutton(htmltextwriter writer,int pageindex)
  {
   writecssclass(writer);
   writer.addattribute(htmltextwriterattribute.href,gethrefstring(pageindex));
   addtooltip(writer,pageindex);
   writer.renderbegintag(htmltextwritertag.a);
   if(pagingbuttontype==pagingbuttontype.image&&morebuttontype==pagingbuttontype.image)
   {
    writer.addattribute(htmltextwriterattribute.src,string.concat(imagepath,"more",buttonimagenameextension,buttonimageextension));
    writer.addattribute(htmltextwriterattribute.border,"0");
    writer.addattribute(htmltextwriterattribute.align,buttonimagealign.tostring());
    writer.renderbegintag(htmltextwritertag.img);
    writer.renderendtag();
   }
   else
    writer.write("...");
   writer.renderendtag();
   writer.addstyleattribute(htmltextwriterstyle.width,pagingbuttonspacing.tostring());
   writer.renderbegintag(htmltextwritertag.span);
   writer.renderendtag();
  }

  #endregion

  #region ipostbackeventhandler implementation

  /// <summary>
  /// 实现<see cref="ipostbackeventhandler"/> 接口,使 <see cref="aspnetpager"/> 控件能够处理将窗体发送到服务器时引发的事件。
  /// </summary>
  /// <param name="args"></param>
  public void raisepostbackevent(string args)
  {
   int pageindex=currentpageindex;
   try
   {
    if(args==null||args=="")
     args=inputpageindex;
    pageindex=int.parse(args);
   }
   catch{}
   onpagechanged(new pagechangedeventargs(pageindex));

  } 
  #endregion 
1