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,如需转载请自行联系原作者
目录
相关文章
|
4天前
|
数据安全/隐私保护
那些酷炫的网页你也可以做到——第六篇,小型公司web开发
那些酷炫的网页你也可以做到——第六篇,小型公司web开发
|
4天前
|
存储 安全 前端开发
第五章 跨域资源共享(CORS):现代Web开发中的关键机制
第五章 跨域资源共享(CORS):现代Web开发中的关键机制
|
2天前
|
Kubernetes 前端开发 JavaScript
未来Web开发的趋势与挑战
随着科技的不断发展,Web开发行业也在不断演进。本文将探讨未来Web开发的趋势和面临的挑战,涵盖了前端、后端以及多种编程语言和数据库相关的技术。
|
4天前
|
JavaScript
js中如何使用工厂方式和构造函数创建对象,web开发项目实例
js中如何使用工厂方式和构造函数创建对象,web开发项目实例
|
4天前
|
JavaScript 前端开发 开发者
在Web开发中,事件处理是一个至关重要的概念
【5月更文挑战第17天】Vue.js的事件处理是其核心特性之一,允许开发者响应用户操作。通过v-on(或@)指令绑定DOM事件到方法,实现交互。事件修饰符如.stop、.prevent等简化处理逻辑。此外,Vue支持自定义事件,便于组件间通信,如子组件通过$emit触发事件,父组件使用v-on监听并响应。理解这些机制能帮助开发者更有效地管理Vue应用的事件流程。
11 0
|
4天前
|
前端开发 JavaScript 算法
探索现代Web开发中的前端框架选择
在现代Web开发中,前端框架的选择是至关重要的。本文将深入探讨各种前端框架的特点和适用场景,帮助开发者了解不同框架的优势和劣势,并为他们提供在项目中做出明智选择的指导。
|
4天前
|
设计模式 存储 前端开发
JS的几种设计模式,Web前端基础三剑客学习知识分享,前端零基础开发
JS的几种设计模式,Web前端基础三剑客学习知识分享,前端零基础开发
|
5天前
|
JSON JavaScript API
使用 Node.js 开发一个简单的 web 服务器响应 HTTP post 请求
使用 Node.js 开发一个简单的 web 服务器响应 HTTP post 请求
16 1
|
5天前
|
JSON JavaScript 中间件
使用 Node.js 开发一个简单的 web 服务器响应 HTTP get 请求
使用 Node.js 开发一个简单的 web 服务器响应 HTTP get 请求
10 2
|
6天前
|
JavaScript 前端开发 API
在Node.js上使用dojo库进行面向对象web应用开发
请注意,虽然这个例子在Node.js环境中使用了Dojo,但Dojo的许多功能(例如DOM操作和AJAX请求)在Node.js环境中可能无法正常工作。因此,如果你打算在Node.js环境中使用Dojo,你可能需要查找一些适用于服务器端JavaScript的替代方案。
17 0