Web用户控件开发--分页控件

简介:

分页是Web应用程序中最常用到的功能之一,在ASP.NET中,虽然自带了一些可以分页的数据控件,但其分页功能并不尽如人意。本文对于这些数据控件的假分页暂且不表,如有不明白的同学请百Google度之。

本文中实现的分页控件是在手动分页基础上做的改善,将分页实现的逻辑部分和数据控件的绑定尽可能分开,以克服手工编写分页代码任务繁琐、代码重用率低等问题。

本文依旧是一粒粟子。

一、分页控件素颜

image

image

image

二、分页控件的实现

本文中将介绍两种将分页实现逻辑与数据控件绑定分离的实现方式:

  • 使用反射机制
  • 使用事件机制

1、基于反射机制的分页控件

源码

PagingHelper.ascx:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="PagingHelper.ascx.cs" Inherits="PagingHelper.Controls.PagingHelper" %>
<div style="width:100%">
    <asp:LinkButton ID="lbtnFirstPage" runat="server" CausesValidation="false" onclick="lbtnPage_Click"  >首页</asp:LinkButton>
    <asp:LinkButton ID="lbtnPrevPage" runat="server" CausesValidation="false"  onclick="lbtnPage_Click" >上一页</asp:LinkButton>
    &nbsp;<asp:Label ID="lbPageIndex" runat="server" Text=""></asp:Label>
    页/共<asp:Label ID="lbTotalPages" runat="server" Text=""></asp:Label>
&nbsp;
    <asp:LinkButton ID="lbtnNextPage" runat="server" CausesValidation="false"  onclick="lbtnPage_Click" >下一页</asp:LinkButton>
    <asp:LinkButton ID="lbtnLastPage" runat="server" CausesValidation="false"  onclick="lbtnPage_Click" >尾页</asp:LinkButton>
</div>

PagingHelper.ascx.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Reflection;
 
namespace PagingHelper.Controls
{
    public partial class PagingHelper : System.Web.UI.UserControl
    {
        #region 属性
        private int m_PageSize;
        public int PageSize         //每页显示记录数
        {
            set
            {
                m_PageSize = value;
            }
            get
            {
                if (m_PageSize.Equals(0))
                {
                    m_PageSize = 10;
                }
                return m_PageSize;
            }
        }
 
        private int m_PageIndex;
        public int PageIndex        //当前页页码
        {
            set
            {
                m_PageIndex = value;
            }
            get
            {
                if (m_PageIndex.Equals(0))
                {
                    m_PageIndex = 1;
                }
                return m_PageIndex;
            }
        }
 
        public int TotalItemCount   //记录总数
        {
            set;
            private get;
        }
 
        public string BindDataMethodName    //绑定数据的方法名
        {
            set;
            private get;
        }
        #endregion
 
        #region 受保护的方法
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                BindPagingHelperControl();
            }
        }
        protected void lbtnPage_Click(object sender, EventArgs e)
        {
            LinkButton lbtn = sender as LinkButton;
            ReBindData(lbtn.CommandArgument);
        }
        #endregion
 
        #region 公共方法
 
        #endregion
 
        #region 私有方法
        private void BindPagingHelperControl()
        {
            int totalPages = (TotalItemCount % PageSize) == 0 ? TotalItemCount / PageSize : TotalItemCount / PageSize + 1;
            //显示
            lbPageIndex.Text = PageIndex.ToString();
            lbTotalPages.Text = totalPages.ToString();
            //使能
            lbtnFirstPage.Enabled = PageIndex > 1;
            lbtnPrevPage.Enabled =  PageIndex > 1;
            lbtnLastPage.Enabled = PageIndex < totalPages;
            lbtnNextPage.Enabled = PageIndex < totalPages;
            //命令
            lbtnFirstPage.CommandArgument = "1";
            lbtnPrevPage.CommandArgument = (PageIndex - 1).ToString();
            lbtnNextPage.CommandArgument = (PageIndex + 1).ToString();
            lbtnLastPage.CommandArgument = totalPages.ToString();
        }
        private void ReBindData(string pageIndex)
        {
            PageIndex = int.Parse(pageIndex);
            Object obj = null;  //空间所在的容器
            if (base.Parent is HtmlForm)
            {
                obj = this.Page;
            }
            else if (base.Parent is ContentPlaceHolder)
            {
                obj = this.Page.Master.Page;
            }
            else
            {
                obj = base.Parent;
            }
            MethodInfo methodInfo = obj.GetType().GetMethod(BindDataMethodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
            methodInfo.Invoke(obj, null);
            BindPagingHelperControl();
        }
        #endregion
 
    }
}

Demo:

Default.aspx:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="PagingHelper.Default" %>
 
<%@ Register src="Controls/PagingHelper.ascx" tagname="PagingHelper" tagprefix="uc1" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:GridView ID="gvDemo" runat="server">
        </asp:GridView>
        <br />
        <uc1:PagingHelper ID="PagingHelper1" runat="server" PageSize="2" />
    </div>
    </form>
</body>
</html>

Default.aspx.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
 
namespace PagingHelper
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            GvDemoBind();
        }
 
        protected void GvDemoBind()
        {
            string sql = @"SELECT * FROM tb_user";
            string sqlCount = @"SELECT COUNT(*) FROM tb_user ";
            int itemStart = (PagingHelper1.PageIndex - 1) * PagingHelper1.PageSize;
            sql += string.Format(" LIMIT {0},{1}",itemStart,PagingHelper1.PageSize);
            gvDemo.DataSource = SQLHelper.ExecuteDataTable(sql).DefaultView;
            gvDemo.DataBind();
            PagingHelper1.TotalItemCount = Convert.ToInt32(SQLHelper.ExecuteScalar(sqlCount));
            PagingHelper1.BindDataMethodName = "GvDemoBind";
        }
    }
}

2、基于事件机制的分页控件

源码:

PagingHelper.ascx:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="PagingHelper.ascx.cs" Inherits="PagingHelper_V2.Controls.PagingHelper" %>
<div style="width:100%">
    <asp:LinkButton ID="lbtnFirstPage" runat="server" CausesValidation="false" onclick="lbtnPage_Click"  >首页</asp:LinkButton>
    <asp:LinkButton ID="lbtnPrevPage" runat="server" CausesValidation="false"  onclick="lbtnPage_Click" >上一页</asp:LinkButton>
    &nbsp;<asp:Label ID="lbPageIndex" runat="server" Text=""></asp:Label>
    页/共<asp:Label ID="lbTotalPages" runat="server" Text=""></asp:Label>
&nbsp;
    <asp:LinkButton ID="lbtnNextPage" runat="server" CausesValidation="false"  onclick="lbtnPage_Click" >下一页</asp:LinkButton>
    <asp:LinkButton ID="lbtnLastPage" runat="server" CausesValidation="false"  onclick="lbtnPage_Click" >尾页</asp:LinkButton>
    &nbsp;转到
    <asp:TextBox ID="txtGoto" runat="server" Width="32px"></asp:TextBox>
<asp:Button ID="btnGoto" runat="server" Text="确定" onclick="btnGoto_Click" />
</div>

PagingHelper.ascx.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
 
namespace PagingHelper_V2.Controls
{
    public partial class PagingHelper : System.Web.UI.UserControl
    {
        #region 属性
        private int m_PageSize;
        public int PageSize         //每页显示记录数
        {
            set
            {
                m_PageSize = value;
            }
            get
            {
                if (m_PageSize.Equals(0))
                {
                    m_PageSize = 10;
                }
                return m_PageSize;
            }
        }
 
        private int m_PageIndex;
        public int PageIndex        //当前页页码
        {
            set
            {
                m_PageIndex = value;
            }
            get
            {
                if (m_PageIndex.Equals(0))
                {
                    m_PageIndex = 1;
                }
                return m_PageIndex;
            }
        }
 
        public int TotalItemCount   //记录总数
        {
            set;
            private get;
        }
 
        #endregion
 
        #region 受保护的方法
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                BindPagingHelperControl();
            }
        }
        protected void lbtnPage_Click(object sender, EventArgs e)
        {
            LinkButton lbtn = sender as LinkButton;
            ReBindData(int.Parse(lbtn.CommandArgument));
        }
        protected void btnGoto_Click(object sender, EventArgs e)
        {
            int gotoPageIndex = PageIndex;
            if (int.TryParse(txtGoto.Text, out gotoPageIndex))
            {
                if (gotoPageIndex < 1 || gotoPageIndex > int.Parse(lbTotalPages.Text))
                {
                    Response.Write("<script>alert('此页面不存在!')</script>");
                }
                else
                {
                    if (!gotoPageIndex.Equals(int.Parse(lbPageIndex.Text)))
                    {
                        ReBindData(gotoPageIndex);
                    }
                }
            }
            else
            {
                Response.Write("<script>alert('请输入正确的页码!')</script>");
            }
 
        }
        #endregion
 
        #region 公共方法
 
        #endregion
 
        #region 私有方法
        private void BindPagingHelperControl()
        {
            int totalPages = (TotalItemCount % PageSize) == 0 ? TotalItemCount / PageSize : TotalItemCount / PageSize + 1;
            //显示
            lbPageIndex.Text = PageIndex.ToString();
            lbTotalPages.Text = totalPages.ToString();
            txtGoto.Text = PageIndex.ToString();
            //使能
            lbtnFirstPage.Enabled = PageIndex > 1;
            lbtnPrevPage.Enabled = PageIndex > 1;
            lbtnLastPage.Enabled = PageIndex < totalPages;
            lbtnNextPage.Enabled = PageIndex < totalPages;
            //命令
            lbtnFirstPage.CommandArgument = "1";
            lbtnPrevPage.CommandArgument = (PageIndex - 1).ToString();
            lbtnNextPage.CommandArgument = (PageIndex + 1).ToString();
            lbtnLastPage.CommandArgument = totalPages.ToString();
        }
        private void ReBindData(int pageIndex)
        {
            PageIndex = pageIndex;
            OnPageIndexChanged(new EventArgs());
            BindPagingHelperControl();
        }
        #endregion
 
        #region 事件
        public delegate void PageIndexChangedEventHandler(object sender, EventArgs e);
        public event PageIndexChangedEventHandler PageIndexChanged;
        protected virtual void OnPageIndexChanged(EventArgs e)
        {
            PageIndexChangedEventHandler handler = PageIndexChanged;
            if (handler != null)
            {
                handler(this, e);
            }
        }
        #endregion
 
        
    }
}

Demo:

Default.aspx:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="PagingHelper_V2.Default" %>
 
<%@ Register src="Controls/PagingHelper.ascx" tagname="PagingHelper" tagprefix="uc1" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:GridView ID="gvDemo" runat="server">
        </asp:GridView>
        &nbsp;
        <uc1:PagingHelper ID="PagingHelper1" runat="server" PageSize="2" OnPageIndexChanged="PagingHelper1_OnPageIndexChanged" />
    </div>
    </form>
</body>
</html>

Default.aspx.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
 
namespace PagingHelper_V2
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            GvDemoBind();
        }
 
        protected void GvDemoBind()
        {
            string sql = @"SELECT * FROM tb_user";
            string sqlCount = @"SELECT COUNT(*) FROM tb_user ";
            int itemStart = (PagingHelper1.PageIndex - 1) * PagingHelper1.PageSize;
            sql += string.Format(" LIMIT {0},{1}", itemStart, PagingHelper1.PageSize);
            gvDemo.DataSource = SQLHelper.ExecuteDataTable(sql).DefaultView;
            gvDemo.DataBind();
            PagingHelper1.TotalItemCount = Convert.ToInt32(SQLHelper.ExecuteScalar(sqlCount));
            
        }
 
        protected void PagingHelper1_OnPageIndexChanged(object sender, EventArgs e)
        {
            GvDemoBind();
        }
    }
}

三、总结

比较两种实现方式,基于事件机制的实现更符合ASP.NET服务器控件的style。

好!那就参照园子里的分页使用基于事件机制的方式再做一个控件作为总结。

源码:

PagingHelper.ascx:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="PagingHelper.ascx.cs" Inherits="PagingHelper_V3.Controls.PagingHelper" %>
<style type="text/css">
    a.LinkButtonDefault{text-align:center;text-decoration:none;margin-right:1px;padding:2px 4px;}
    a.LinkButtonBlue{background: #ebebeb;text-align:center;text-decoration:none;margin-right:1px;padding:2px 4px;}
    a.LinkButtonYellow { background-color:#ccc; color:#000fff; font-weight:bold;text-align:center;text-decoration:none;margin-right:1px;padding:2px 4px;}
</style>
<div style="width:100%">
<asp:Label ID="lbTotalPages" runat="server" ForeColor="#fff"></asp:Label>页:
    <asp:LinkButton ID="lbtnFirstPage" runat="server" CausesValidation="false" CssClass="LinkButtonDefault" onclick="lbtnPage_Click" >首页</asp:LinkButton>
    <asp:LinkButton ID="lbtnPrevPage" runat="server" CausesValidation="false" CssClass="LinkButtonDefault" onclick="lbtnPage_Click" >上一页</asp:LinkButton>
    <asp:Repeater ID="rptPageNumber" runat="server">
        <ItemTemplate>
            <asp:LinkButton ID="lbtnPageNumber" runat="server" CausesValidation="false" Width="16px" onclick="lbtnPage_Click"
                 CssClass='<%# Convert.ToInt32(Container.DataItem)==PageIndex?"LinkButtonYellow":"LinkButtonBlue"%>' CommandArgument='<%# Container.DataItem %>'>
<%
   1: #Container.DataItem 
%>
            </asp:LinkButton>
        </ItemTemplate>
    </asp:Repeater>
    <asp:LinkButton ID="lbtnNextPage" runat="server" CausesValidation="false" CssClass="LinkButtonDefault"  onclick="lbtnPage_Click" >下一页</asp:LinkButton>
    <asp:LinkButton ID="lbtnLastPage" runat="server" CausesValidation="false" CssClass="LinkButtonDefault"  onclick="lbtnPage_Click" >尾页</asp:LinkButton>
</div>

PagingHelper.ascx.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
 
namespace PagingHelper_V3.Controls
{
    public partial class PagingHelper : System.Web.UI.UserControl
    {
        #region 属性
        private int m_PageSize;
        public int PageSize         //每页显示记录数
        {
            set
            {
                m_PageSize = value;
            }
            get
            {
                if (m_PageSize.Equals(0))
                {
                    m_PageSize = 10;
                }
                return m_PageSize;
            }
        }
 
        private int m_PageIndex;
        public int PageIndex        //当前页页码
        {
            set
            {
                m_PageIndex = value;
            }
            get
            {
                if (m_PageIndex.Equals(0))
                {
                    m_PageIndex = 1;
                }
                return m_PageIndex;
            }
        }
 
        public int TotalItemCount   //记录总数
        {
            set;
            private get;
        }
 
        #endregion
 
        #region 受保护的方法
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                BindPagingHelperControl();
            }
        }
        protected void lbtnPage_Click(object sender, EventArgs e)
        {
            LinkButton lbtn = sender as LinkButton;
            ReBindData(int.Parse(lbtn.CommandArgument));
        }
        #endregion
 
        #region 公共方法
 
        #endregion
 
        #region 私有方法
        private void BindPageNum(int totalPages)
        {
            int startPageIndex = 1, endPageIndex = 10;
            if (totalPages < endPageIndex)
            {
                endPageIndex = totalPages;
            }
            else
            {
                startPageIndex = (PageIndex > 5) ? PageIndex - 5 : startPageIndex;
                int result = (startPageIndex + 9) - totalPages;
                if (result > 0)
                {
                    endPageIndex = totalPages;
                    startPageIndex -= result;
                }
                else
                {
                    endPageIndex = startPageIndex + 9;
                }
            }
            BindPageNum(startPageIndex, endPageIndex);
        }
        private void BindPageNum(int startPageIndex, int endPageIndex)
        {
            int[] pages = new int[endPageIndex - startPageIndex + 1];
            int index = 0;
            for (int i = startPageIndex; i <= endPageIndex; i++)
            {
                pages[index] = i;
                index++;
            }
            rptPageNumber.DataSource = pages;
            rptPageNumber.DataBind();
        }
        private void BindPagingHelperControl()
        {
            int totalPages = (TotalItemCount % PageSize) == 0 ? TotalItemCount / PageSize : TotalItemCount / PageSize + 1;
            //显示
            lbTotalPages.Text = totalPages.ToString();
            BindPageNum(totalPages);
            //使能
            lbtnFirstPage.Enabled = PageIndex > 1;
            lbtnPrevPage.Enabled = PageIndex > 1;
            lbtnLastPage.Enabled = PageIndex < totalPages;
            lbtnNextPage.Enabled = PageIndex < totalPages;
            //命令
            lbtnFirstPage.CommandArgument = "1";
            lbtnPrevPage.CommandArgument = (PageIndex - 1).ToString();
            lbtnNextPage.CommandArgument = (PageIndex + 1).ToString();
            lbtnLastPage.CommandArgument = totalPages.ToString();
        }
        private void ReBindData(int pageIndex)
        {
            PageIndex = pageIndex;
            OnPageIndexChanged(new EventArgs());
            BindPagingHelperControl();
        }
        #endregion
 
        #region 事件
        public delegate void PageIndexChangedEventHandler(object sender, EventArgs e);
        public event PageIndexChangedEventHandler PageIndexChanged;
        protected virtual void OnPageIndexChanged(EventArgs e)
        {
            PageIndexChangedEventHandler handler = PageIndexChanged;
            if (handler != null)
            {
                handler(this, e);
            }
        }
        #endregion
    }
}
作者: 韩兆新
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
分类:  [06]ASP.NET相关
标签:  ASP.NET

本文转自韩兆新博客博客园博客,原文链接:http://www.cnblogs.com/hanzhaoxin/p/3871703.html,如需转载请自行联系原作者
目录
相关文章
|
19天前
|
监控 JavaScript 前端开发
《理解 WebSocket:Java Web 开发的实时通信技术》
【4月更文挑战第4天】WebSocket是Java Web实时通信的关键技术,提供双向持久连接,实现低延迟、高效率的实时交互。适用于聊天应用、在线游戏、数据监控和即时通知。开发涉及服务器端实现、客户端连接及数据协议定义,注意安全、错误处理、性能和兼容性。随着实时应用需求增加,WebSocket在Java Web开发中的地位将更加重要。
|
30天前
|
Web App开发 前端开发 开发工具
介绍Web开发的基础知识
介绍Web开发的基础知识
29 7
|
5天前
|
JSON Java fastjson
Spring Boot 底层级探索系列 04 - Web 开发(2)
Spring Boot 底层级探索系列 04 - Web 开发(2)
15 0
|
5天前
|
安全 编译器 PHP
PHP 8.1版本发布:引领Web开发新潮流
PHP编程语言一直是Web开发的主力军,而最新发布的PHP 8.1版本则为开发者们带来了更多创新和便利。本文将介绍PHP 8.1版本的主要特性,包括更快的性能、新的语言功能和增强的安全性,以及如何利用这些功能来提升Web应用程序的质量和效率。
|
8天前
|
PHP
web简易开发——通过php与HTML+css+mysql实现用户的登录,注册
web简易开发——通过php与HTML+css+mysql实现用户的登录,注册
|
8天前
|
前端开发 数据挖掘 API
使用Python中的Flask框架进行Web应用开发
【4月更文挑战第15天】在Python的Web开发领域,Flask是一个备受欢迎的轻量级Web框架。它简洁、灵活且易于扩展,使得开发者能够快速地构建出高质量的Web应用。本文将深入探讨Flask框架的核心特性、使用方法以及在实际开发中的应用。
|
17天前
|
安全 前端开发 Java
Java Web开发知识点学习总结
Java Web开发涉及Java基础、Servlet、JSP、数据库操作(SQL+JDBC)、MVC设计模式、Spring框架、Hibernate ORM、Web服务(SOAP&RESTful)、安全认证(HTTP Basic/Digest/OAuth)及性能优化(缓存、异步、负载均衡)。
16 3
|
20天前
|
XML JSON JavaScript
使用JSON和XML:数据交换格式在Java Web开发中的应用
【4月更文挑战第3天】本文比较了JSON和XML在Java Web开发中的应用。JSON是一种轻量级、易读的数据交换格式,适合快速解析和节省空间,常用于API和Web服务。XML则提供更强的灵活性和数据描述能力,适合复杂数据结构。Java有Jackson和Gson等库处理JSON,JAXB和DOM/SAX处理XML。选择格式需根据应用场景和需求。
|
24天前
|
前端开发 JavaScript 数据管理
描述一个使用Python开发Web应用程序的实际项目经验,包括所使用的框架和技术栈。
使用Flask开发Web应用,结合SQLite、Flask-SQLAlchemy进行数据管理,HTML/CSS/JS(Bootstrap和jQuery)构建前端。通过Flask路由处理用户请求,模块化代码提高可维护性。unittest进行测试,开发阶段用内置服务器,生产环境可选WSGI服务器或容器化部署。实现了用户注册登录和数据管理功能,展示Python Web开发的灵活性和效率。
14 4
|
30天前
|
API
2024常用Web支付开发讲解教程
本教程为web支付开发,讲解了最常用的两钟支付:支付宝支付和微信支付,服务器配置和API对接,学完本课程可以学会微信支付、和支付宝支付开发。
18 2
2024常用Web支付开发讲解教程