• 自己动手开发服务器控件分页控件 up


    对于一个大型业务系统来说,数据分页显示,是必不可少的。

    但是怎么分、用什么分,方法和工具就有很多了。。。

    刚入门的时候,总是会很习惯的从工具箱中拖出一个GridView,加上AllowPaging="true",再写个OnPageIndexChanging事件,OK,分页实现了。。。

    发现这种方式效率差后,就开始拖.Net3.5中的独立分页控件了,忘了叫什么名字,公司用.Net2.0,没办法。

    这些方式,基本上都是一次就查出所有数据,再分页。

    ------------------------------------------------------------------------------------------------------------------------------------------------

    当然了,需要第几页就查第几页的数据,这才是最好的。 

    所以,后来,也很傻的自己拖4个按钮(第一页、上一页、下一页、最后一页),一个下拉框(当前第N页),

    然后为每个按钮写Click事件,为下拉框写Change事件,再配上分页存储过程,

    嗯,是比之前几种方式要快一些。就是太繁琐,显然几乎没人会这么干。

     ------------------------------------------------------------------------------------------------------------------------------------------------

    这会就有了做个简单的分页控件的想法,可是又不会,也没做过。

    好吧,中关村买书去。。。

    边看书边琢磨了两天,终于出来了。。。

    不需要很强大,不需要很华丽,只要。。。够用就行。

     

    加上CSS样式,最终显示效果就是这样,应该够用吧?反正我们是够了。。。哈哈


    ------------------------------------------------------------------------------------------------------------------------------------------------

    首先,这是一个组合控件,5个按钮+1个输入框构成。

    原理是让这5个按钮都调用同一个方法,同时再根据点击的按钮来判断页索引。

    开始贴代码吧:

    控件声明
     1 //设置控件在页面中的显示代码,如<Feli:Pager .....>
    2 [assembly: TagPrefix("FeliControls", "Feli")]
    3 namespace FeliControls
    4 {
    5 [DefaultProperty("ShowCountInfo")]//在VS属性栏中默认选中的属性
    6 [DefaultEvent("PageIndexChanged")]//默认事件,设置后,双击控件就进入CS代码中该事件的声明,如Button控件的这个属性就是Click
    7 [ToolboxData("<{0}:Pager runat=server></{0}:Pager>")]//在页面中调用时的显示代码
    8 publicclass Pager : CompositeControl
    9 {
    10 //继承自CompositeControl,即组合控件
    11 }
    12 }


    然后呢,就是各个子控件了。

    子控件声明
    1 private Button btnFirst;
    2 private Button btnPrev;
    3 private Button btnNext;
    4 private Button btnLast;
    5 private Button btnDiy;
    6
    7 private TextBox txtPageIndex;

    接着呢,这些个按钮的文字,得允许自己设置吧。

    子控件属性
      1         [Bindable(true)]
    2 [Category("Appearance")]//在VS属性栏中所属的分组
    3 [DefaultValue("")]
    4 [Localizable(true)]
    5 [Description("是否显示数据总数及当前显示数据信息")]//显示在VS属性栏下页的描述信息
    6 publicbool ShowCountInfo
    7 {
    8 get
    9 {
    10 bool s =true;
    11 if(!this.DesignMode)//非设计模式才取ViewState
    12 {
    13 if (ViewState["ShowCountInfo"] !=null)
    14 {
    15 s = (bool)ViewState["ShowCountInfo"];
    16 }
    17 }
    18 return s;
    19 }
    20
    21 set
    22 {
    23 ViewState["ShowCountInfo"] = value;
    24 }
    25 }
    26 ///<summary>
    27 /// 第一页按钮文字描述
    28 ///</summary>
    29 [Bindable(true)]
    30 [Category("分页按钮属性")]
    31 [DefaultValue("")]
    32 [Localizable(true)]
    33 [Description("第一页按钮文字")]
    34 publicstring FirstPageText
    35 {
    36 get
    37 {
    38 EnsureChildControls();
    39 return btnFirst.Text;
    40 }
    41
    42 set
    43 {
    44 EnsureChildControls();
    45 btnFirst.Text = value;
    46 }
    47 }
    48 ///<summary>
    49 /// 上一页按钮文字描述
    50 ///</summary>
    51 [Bindable(true)]
    52 [Category("分页按钮属性")]
    53 [DefaultValue("")]
    54 [Localizable(true)]
    55 [Description("上一页按钮文字")]
    56 publicstring PrevPageText
    57 {
    58 get
    59 {
    60 EnsureChildControls();
    61 return btnPrev.Text;
    62 }
    63
    64 set
    65 {
    66 EnsureChildControls();
    67 btnPrev.Text = value;
    68 }
    69 }
    70 ///<summary>
    71 /// 下一页按钮文字描述
    72 ///</summary>
    73 [Bindable(true)]
    74 [Category("分页按钮属性")]
    75 [DefaultValue("")]
    76 [Localizable(true)]
    77 [Description("下一页按钮文字")]
    78 publicstring NextPageText
    79 {
    80 get
    81 {
    82 EnsureChildControls();
    83 return btnNext.Text;
    84 }
    85
    86 set
    87 {
    88 EnsureChildControls();
    89 btnNext.Text = value;
    90 }
    91 }
    92 ///<summary>
    93 /// 最后一页按钮文字描述
    94 ///</summary>
    95 [Bindable(true)]
    96 [Category("分页按钮属性")]
    97 [DefaultValue("")]
    98 [Localizable(true)]
    99 [Description("最后一页按钮文字")]
    100 publicstring LastPageText
    101 {
    102 get
    103 {
    104 EnsureChildControls();
    105 return btnLast.Text;
    106 }
    107
    108 set
    109 {
    110 EnsureChildControls();
    111 btnLast.Text = value;
    112 }
    113 }
    114
    115 ///<summary>
    116 /// GO按钮文字描述
    117 ///</summary>
    118 [Bindable(true)]
    119 [Category("分页按钮属性")]
    120 [DefaultValue("")]
    121 [Localizable(true)]
    122 [Description("自定义跳转到页面按钮文字")]
    123 publicstring BtnGoText
    124 {
    125 get
    126 {
    127 EnsureChildControls();
    128 return btnDiy.Text;
    129 }
    130
    131 set
    132 {
    133 EnsureChildControls();
    134 btnDiy.Text = value;
    135 }
    136 }

    嗯,还有分页(第几页、数据总数、每页显示几条等)数量信息

    分页属性相关
      1 publicint CurrentPageIndex
    2 {
    3 get
    4 {
    5 int idx =1;
    6 if (!this.DesignMode)
    7 {
    8 if (txtPageIndex.Text !=null&& txtPageIndex.Text !="")
    9 {
    10 idx = Convert.ToInt32(txtPageIndex.Text.Trim());
    11 }
    12 }
    13 return idx;
    14 }
    15 set
    16 {
    17 EnsureChildControls();//确认子控件已创建,未创建则会调用下面的CreateChildControls方法
    18
    19 if (value <2)
    20 {
    21 value =1;
    22 }
    23 if (value >=this.PageCount)
    24 {
    25 value =this.PageCount;
    26 }
    27 if (ViewState["CurrentPageIndex"] !=null)
    28 {
    29 string strPage = ViewState["CurrentPageIndex"].ToString();
    30 }
    31 txtPageIndex.Text = value.ToString();
    32 }
    33 }
    34 ///<summary>
    35 /// 总页数
    36 ///</summary>
    37 publicint PageCount
    38 {
    39 get
    40 {
    41 if (this.DesignMode)
    42 {
    43 return0;
    44 }
    45 else
    46 {
    47 return RecordCount % PageSize ==0? RecordCount / PageSize : (RecordCount / PageSize) +1;//直接计算共有多少页
    48 }
    49 }
    50 }
    51 ///<summary>
    52 /// 每页显示的记录数
    53 ///</summary>
    54 [Bindable(true)]
    55 [Category("分页信息")]
    56 [DefaultValue("")]
    57 [Localizable(true)]
    58 [Description("每页显示的数据数")]
    59 publicint PageSize
    60 {
    61 get
    62 {
    63 int _size =30;
    64 if (!this.DesignMode)
    65 {
    66 if (ViewState["PageSize"] !=null)
    67 {
    68 _size = (int)ViewState["PageSize"];
    69 }
    70 }
    71 return _size;
    72 }
    73 set
    74 {
    75 ViewState["PageSize"] = value;
    76 }
    77 }
    78
    79 ///<summary>
    80 /// 总记录数
    81 ///</summary>
    82 [Bindable(true)]
    83 [Category("分页信息")]
    84 [DefaultValue("")]
    85 [Localizable(true)]
    86 [Description("总记录数")]
    87 publicint RecordCount
    88 {
    89 get
    90 {
    91 int idx =0;
    92 if (!this.DesignMode)
    93 {
    94 if (ViewState["RecordCount"] !=null)
    95 {
    96 idx = (int)ViewState["RecordCount"];
    97 }
    98 }
    99 return idx;
    100 }
    101 set
    102 {
    103 ViewState["RecordCount"] = value;
    104 }
    105 }

    因为自定义服务器控件,未重写HTML标签的话,好像都是<span>,所以就重写了下,用DIV

    重写控件生成的HTML代码标签
     1 ///<summary>
    2 /// 重写控件HTML代码开始标签
    3 ///</summary>
    4 protectedoverride HtmlTextWriterTag TagKey
    5 {
    6 get
    7 {
    8 return HtmlTextWriterTag.Div;
    9 }
    10 }

    接下来创建子控件了

    创建子控件
     1 protectedoverridevoid CreateChildControls()
    2 {
    3 this.Controls.Clear();//先清除现有的控件
    4
    5 btnFirst =new Button();
    6 btnFirst.ID ="btnFirst";
    7 btnFirst.CommandName ="Page";
    8 btnFirst.CommandArgument ="ButtonFirst";
    9 btnFirst.Click +=new EventHandler(Change_PageIndex);//绑上单击事件
    10 btnFirst.Text ="第一页";
    11 btnFirst.CssClass ="input_border felipager_btn_first";
    12
    13 this.Controls.Add(btnFirst);
    14
    15 btnPrev =new Button();
    16 btnPrev.ID ="btnPrev";
    17 btnPrev.CommandName ="Page";
    18 btnPrev.CommandArgument ="ButtonPrev";
    19 btnPrev.Click +=new EventHandler(Change_PageIndex);
    20 btnPrev.Text ="上一页";
    21 btnPrev.CssClass ="input_border mr20 felipager_btn_prev";
    22
    23 this.Controls.Add(btnPrev);
    24
    25 btnNext =new Button();
    26 btnNext.ID ="btnNext";
    27 btnNext.CommandName ="Page";
    28 btnNext.CommandArgument ="ButtonNext";
    29 btnNext.Click +=new EventHandler(Change_PageIndex);
    30 btnNext.Text ="下一页";
    31 btnNext.CssClass ="input_border ml20 felipager_btn_next";
    32
    33 this.Controls.Add(btnNext);
    34
    35 btnLast =new Button();
    36 btnLast.ID ="btnLast";
    37 btnLast.CommandName ="Page";
    38 btnLast.CommandArgument ="ButtonLast";
    39 btnLast.Click +=new EventHandler(Change_PageIndex);
    40 btnLast.Text ="最后一页";
    41 btnLast.CssClass ="input_border felipager_btn_last";
    42
    43 this.Controls.Add(btnLast);
    44
    45 btnDiy =new Button();
    46 btnDiy.ID ="btnDiy";
    47 btnDiy.CommandName ="Page";
    48 btnDiy.CommandArgument ="ButtonDiy";
    49 btnDiy.Click +=new EventHandler(Change_PageIndex);
    50 btnDiy.Text ="GO";
    51 btnDiy.CssClass ="input_border felipager_btn_go";
    52
    53 this.Controls.Add(btnDiy);
    54
    55 txtPageIndex =new TextBox();
    56 txtPageIndex.ID ="txtPageIndex";
    57 txtPageIndex.Width =30;
    58 txtPageIndex.CssClass ="input_border felipager_txt_pageindex";
    59
    60 this.Controls.Add(txtPageIndex);
    61
    62 base.CreateChildControls();
    63 }

    可以看到,5个按钮都会触发同一事件。

    各按钮单击事件
     1 void Change_PageIndex(object sender, EventArgs e)
    2 {
    3 //触发了点击事件,则将blnNoClick设为false.
    4 blnNoClick =false;
    5 Button btn = (Button)sender;
    6 if (btn.CommandName =="Page")
    7 {
    8 PageChangedEventArgs ee =new PageChangedEventArgs();
    9 if (btn.CommandArgument =="ButtonFirst")
    10 {
    11 this.CurrentPageIndex =1;
    12 }
    13 if (btn.CommandArgument =="ButtonPrev")
    14 {
    15 this.CurrentPageIndex -=1;
    16 }
    17 if (btn.CommandArgument =="ButtonNext")
    18 {
    19 this.CurrentPageIndex +=1;
    20 }
    21 if (btn.CommandArgument =="ButtonLast")
    22 {
    23 this.CurrentPageIndex =this.PageCount;
    24 }
    25 if (btn.CommandArgument =="ButtonDiy")
    26 {
    27 int intDiyIdx =1;
    28 //如果输入数字不合法,则跳转到第一页
    29 if (int.TryParse(this.txtPageIndex.Text, out intDiyIdx))
    30 {
    31 if (intDiyIdx >0)
    32 {
    33 this.CurrentPageIndex = intDiyIdx;
    34 }
    35 else
    36 {
    37 this.Page.RegisterStartupScript("tishi", "<script>alert('页索引必须为大于0的整数');</script>");
    38 this.CurrentPageIndex =1;
    39 }
    40 }
    41 else
    42 {
    43 this.Page.RegisterStartupScript("tishi", "<script>alert('页索引必须为整数');</script>");
    44 this.CurrentPageIndex =1;
    45 }
    46 }
    47 ee.CurrentPageIndex =this.CurrentPageIndex;
    48 ee.PageCount =this.PageCount;
    49 ee.PageSize =this.PageSize;
    50 ee.RecordCount =this.RecordCount;
    51 this.OnPageIndexChanged(ee);
    52 }

    最后就是渲染控件了

    渲染控件
     1 protectedoverridevoid RenderContents(HtmlTextWriter output)
    2 {
    3 output.AddAttribute(HtmlTextWriterAttribute.Class, "felipager_displayinfo");
    4 output.RenderBeginTag(HtmlTextWriterTag.Div);
    5 //如果需要显示数据总数信息,则显示
    6 if (this.ShowCountInfo)
    7 {
    8 int intStart =this.PageSize * (this.CurrentPageIndex -1);
    9 if (intStart <1)
    10 {
    11 intStart =0;
    12 }
    13 int intEnd =this.PageSize *this.CurrentPageIndex;
    14 if (intEnd >this.RecordCount)
    15 {
    16 intEnd =this.RecordCount;
    17 }
    18 intStart +=1;//每页的第一条的序号应该是1,而不是0
    19 output.Write("共有 {0} 条数据,当前显示 {1} - {2} 条", this.RecordCount, intStart, intEnd);
    20 }
    21 output.RenderEndTag();
    22
    23 output.AddAttribute(HtmlTextWriterAttribute.Class, "felipager_navbox");
    24 output.RenderBeginTag(HtmlTextWriterTag.Div);
    25
    26 #region ----控制导航按钮状态
    27
    28 //如果是第一页,则该按钮不可用
    29 if (this.CurrentPageIndex ==1)
    30 {
    31 btnFirst.Enabled =false;
    32 }
    33 else
    34 {
    35 btnFirst.Enabled =true;
    36 }
    37 //如果是第一页,则该按钮不可用
    38 if (this.CurrentPageIndex ==1)
    39 {
    40 btnPrev.Enabled =false;
    41 }
    42 else
    43 {
    44 btnPrev.Enabled =true;
    45 }
    46 //如果是最后一页,则该按钮不可用
    47 if (this.CurrentPageIndex >=this.PageCount)
    48 {
    49 btnNext.Enabled =false;
    50 }
    51 else
    52 {
    53 btnNext.Enabled =true;
    54 }
    55 //如果是最后一页,则该按钮不可用
    56 if (this.CurrentPageIndex >=this.PageCount)
    57 {
    58 btnLast.Enabled =false;
    59 }
    60 else
    61 {
    62 btnLast.Enabled =true;
    63 }
    64 //如果只有一页,则该按钮不可用
    65 if (this.PageCount <=1)
    66 {
    67 btnDiy.Enabled =false;
    68 }
    69 else
    70 {
    71 btnDiy.Enabled =true;
    72 }
    73 //如果只有一页,则该输入框不可用
    74 if (this.PageCount <=1)
    75 {
    76 txtPageIndex.Enabled =false;
    77 }
    78 else
    79 {
    80 txtPageIndex.Enabled =true;
    81 }
    82
    83 #endregion
    84
    85 btnFirst.RenderControl(output);
    86 btnPrev.RenderControl(output);
    87 output.Write("当前第");
    88 txtPageIndex.Text =this.CurrentPageIndex.ToString();
    89 txtPageIndex.RenderControl(output);
    90 btnDiy.RenderControl(output);
    91 output.Write("页,共{0}页", this.PageCount);
    92 btnNext.RenderControl(output);
    93 btnLast.RenderControl(output);
    94
    95 output.RenderEndTag();
    96 }

    不过还缺了点东西,因为点击按钮时,分页控件需要将接下来要显示的页索引告诉分页方法,这样分页方法才知道需要去查询第几页的数据。

    所以,我就写了这个。

    分页控件事件参数
     1 ///<summary>
    2 /// 分页控件事件参数类
    3 ///</summary>
    4 publicclass PageChangedEventArgs:System.EventArgs
    5 {
    6 public PageChangedEventArgs()
    7 { }
    8 ///<summary>
    9 /// 当前页索引
    10 ///</summary>
    11 privateint intCurrentPageIndex;
    12 publicnewint CurrentPageIndex
    13 {
    14 get { return intCurrentPageIndex; }
    15 set { intCurrentPageIndex = value; }
    16 }
    17 ///<summary>
    18 /// 数据总页数
    19 ///</summary>
    20 privateint intPageCount;
    21 publicnewint PageCount
    22 {
    23 get { return intPageCount; }
    24 set { intPageCount = value; }
    25 }
    26 ///<summary>
    27 /// 每页显示的记录数
    28 ///</summary>
    29 privateint intPageSize;
    30 publicnewint PageSize
    31 {
    32 get { return intPageSize; }
    33 set { intPageSize = value; }
    34 }
    35 ///<summary>
    36 /// 数据总数
    37 ///</summary>
    38 privateint intRecordCount;
    39 publicnewint RecordCount
    40 {
    41 get { return intRecordCount; }
    42 set { intRecordCount = value; }
    43 }
    44 }


    ------------------------------------------------------------------------------------------------------------------------------------------------

    再来看看这控件怎么用吧

    <Feli:Pager ID="fpgHistoryList" CssClass="felipager_main" runat="server" OnPageIndexChanged="fpgHistoryList_PageIndexChanged" /> 

    当然,还需要设置每页显示的记录数及数据总数

    this.fpgHistoryList.PageSize = 20;

    this.fpgHistoryList.RecordCount = 600;

    还有分页事件

    分页事件
    1 ///<summary>
    2 /// 分页事件
    3 ///</summary>
    4 protectedvoid fpgHistoryList_PageIndexChanged(object sender, FeliControls.PageChangedEventArgs e)
    5 {
    6 BindPagedData(e.CurrentPageIndex);
    7 }

    到这,就全部结束了。。。(各CSS样式,可根据需要自己定义)

    点此下载全部代码

    初学的成果,难免有不完善或错误的地方,若发现了,还请指出,不胜感激!!!

  • 相关阅读:
    SQL Server Always on 日志收缩
    jq 获取某个元素是否鼠标悬停
    百度地图BMap实现在行政区域内做标注
    2021年终折腾总结
    ssr服务端渲染搭建
    windbg解决服务器cpu过高问题
    【工具】Java实现MD5算法
    【原创】Java创建对象与C++创建对象的比较
    【原创】C# 文件操作详解(二)FileInfo类
    【原创】JavaEE项目问题总结(1)
  • 原文地址:https://www.cnblogs.com/uphenson/p/2112896.html
Copyright © 2020-2023  润新知