=x= 🌵 Web Forms 使用者控制项-制作分页功能。
📌 游艇网页的 NEWS 新闻列表页底部的分页功能,算是专案的後端功能里比较难的部分,制作时会使用到 "Web Forms 使用者控制项" 来自制控制项,制作完毕後拖拉进页面就可以使用,新闻列表页使用时也会用到比较复杂的 SQL 语法来搭配,分页控制项包含资料总数的呈现,相同资料量但因为每页呈现的数量不同,分页号码项目会因为页数多寡而有不同的效果,可以参考下方截图 :
<asp:Literal ID="litPage" runat="server"></asp:Literal>
//设定自制控制项属性接收值的类型
public int totalItems { get; set; } //总共几笔资料
public int limit { get; set; } //一页几笔资料
public string targetPage { get; set; } //作用页面完整网页名称
#region "用正规式判断是否为数字"
/// <summary>
/// 用正规式判断是否为数字
/// </summary>
/// <param name="inputData">输入字串</param>
/// <returns>bool</returns>
bool IsNumber(string inputData)
{
return System.Text.RegularExpressions.Regex.IsMatch(inputData, "^[0-9]+$");
}
#endregion
public void showPageControls()
{
litPage.Text = ""; //清空分页控制项
int page = 1; //预设第1页
//如果网址有传值
if (!string.IsNullOrEmpty(Request["page"])) {
//传值为数字
if (IsNumber(Request["page"])) {
page = Convert.ToInt16(Request["page"]); //修改当前页码
}
}
if (totalItems == 0) {
return;
}
if (limit == 0) {
return;
}
//确认当前页面档案名称非 null 在 ?? 左侧非 null 则不变,左侧是 null 则传回右侧结果
targetPage = targetPage ?? System.IO.Path.GetFileName(Request.PhysicalPath);
//渲染分页控制项 //邻近页 adjacents 参数不建议设太大,可能导致换行
litPage.Text = getPaginationString(page, totalItems, limit, 2, targetPage);
}
#region "产生分页控制项"
/// <summary>
/// 产生分页控制项
/// </summary>
/// <param name="page">目前第几页</param>
/// <param name="totalItems">共有几笔</param>
/// <param name="limit">一页几笔资料</param>
/// <param name="adjacents">邻近页左右各几笔,两侧隐藏时只显示当前页左右各几页,不可为0,值设太大可能导致换行,建议值为2</param>
/// <param name="targetPage">当前页面档案名称,例:index.aspx</param>
/// <returns>回传HTML标签字串</returns>
public static string getPaginationString(int page, int totalItems, int limit, int adjacents, string targetPage)
{
//判断预设网页有无带有传值用,如果有出现 ? 表示已有传参数就在後面加 & 加挂,如无则补加 ? //预设在档名後加问号
targetPage = targetPage.IndexOf('?') != -1 ? targetPage + "&" : targetPage + "?";
//前一页 = 目前页面-1
int prev = page-1;
//下一页 = 目前页面+1
int nextPage = page+1;
//总页数数值 = 总资料笔数/每页几笔
Double value = Convert.ToDouble((decimal)totalItems / limit);
//最末页(总页数) = 总页数数值无条件进位成整数
int lastpage = Convert.ToInt16(Math.Ceiling(value));
//倒数第二页 = 最末页-1
int secondLast = lastpage-1;
//逻辑判断共用参数
int commonParameter = 3+(adjacents*2); //不可修改:"3"代表当前页+首或末两页,"2"代表左右侧页
//建立分页 HTML 字串逻辑
StringBuilder paginationBuilder = new StringBuilder();
//超过1页才显示分页控制项
if (lastpage > 1) {
//共计几笔资料 HTML
paginationBuilder.Append("<div class=\"pagination\">Total <span style=\"color:red\" >" + totalItems + "</span> data.");
//上一页HTML,目前页面大於1则启用连结,否则就禁用
paginationBuilder.Append(page > 1 ? string.Format("<a href=\"{0}page={1}\"> <<< </a>", targetPage, prev) : "<span class=\"disabled\"> <<< </span>");
//页码选项 HTML 逻辑判断
//总页数 不多於 (逻辑判断共用参数+(3=代表当前页+首或末两页),就不隐藏页码
if (lastpage <= commonParameter+3) {
for (int counter = 1; counter <= lastpage; counter++) {
//counter等於当前页则不加入连结,否则就加入连结
paginationBuilder.Append(counter == page ? string.Format("<span class=\"current\">{0}</span>", counter) : string.Format("<a href=\"{0}page={1}\">{1}</a>", targetPage, counter));
}
}
//执行隐藏页码
else {
//只隐藏右侧页码
if (page < commonParameter) {
for (int counter = 1; counter <= commonParameter; counter++) {
paginationBuilder.Append(counter == page ? string.Format("<span class=\"current\">{0}</span>", counter) : string.Format("<a href=\"{0}page={1}\">{1}</a>", targetPage, counter));
}
//之後的页码用...省略
paginationBuilder.Append("...");
//加入倒数第2页
paginationBuilder.Append(string.Format("<a href=\"{0}page={1}\">{1}</a>", targetPage, secondLast));
//加入最末页
paginationBuilder.Append(string.Format("<a href=\"{0}page={1}\">{1}</a>", targetPage, lastpage));
}
//中间页码,隐藏两侧页码
else if (page >= commonParameter && page <= lastpage-commonParameter) {
//加入第一页+第二页及...省略页码
paginationBuilder.Append(string.Format("<a href=\"{0}page=1\">1</a>", targetPage));
paginationBuilder.Append(string.Format("<a href=\"{0}page=2\">2</a>", targetPage));
paginationBuilder.Append("...");
for (int counter = page-adjacents; counter <= page+adjacents; counter++) {
//从当前页的左侧邻近页到右侧邻近页正常添加页码 (当前页不加连结)
paginationBuilder.Append(counter == page ? string.Format("<span class=\"current\">{0}</span>", counter) : string.Format("<a href=\"{0}page={1}\">{1}</a>", targetPage, counter));
}
//之後的页码用...省略,加入倒数第二页及最末页
paginationBuilder.Append("...");
paginationBuilder.Append(string.Format("<a href=\"{0}page={1}\">{1}</a>", targetPage, secondLast));
paginationBuilder.Append(string.Format("<a href=\"{0}page={1}\">{1}</a>", targetPage, lastpage));
}
////只隐藏左侧页码
else {
//加入第一页+第二页及...省略页码
paginationBuilder.Append(string.Format("<a href=\"{0}page=1\">1</a>", targetPage));
paginationBuilder.Append(string.Format("<a href=\"{0}page=2\">2</a>", targetPage));
paginationBuilder.Append("...");
for (int counter = lastpage-commonParameter; counter <= lastpage; counter++) {
paginationBuilder.Append(counter == page ? string.Format("<span class=\"current\">{0}</span>", counter) : string.Format("<a href=\"{0}page={1}\">{1}</a>", targetPage, counter));
}
}
}
//下一页的 HTML 内容,目前页面小於最末页则启用连结,否则就禁用
paginationBuilder.Append(page < lastpage ? string.Format("<a href=\"{0}page={1}\">>>></a>", targetPage, nextPage) : "<span class=\"disabled\"> >>> </span>");
paginationBuilder.Append("</div>\r\n");
}
return paginationBuilder.ToString();
}
#endregion
🌵 於方法上方输入///
可自动快速生成注释行,可对方法内容加入说明 (中文区域)。
👀 自制分页控制项完整程序码参考 : 专案 GitHub 连结
<uc1:WebUserControl_Page runat="server" ID="WebUserControl_Page" />
<head>
标签内引入 pagination.css 分页样式,CSS 内容参考如下div#pagination {
height: 50px;
margin-top: 3px;
}
div#pagination .count {
float: left;
padding: 5px;
}
div#pagination .pages {
float: right;
padding: 5px;
}
div#paginationTop .count {
float: left;
padding: 5px;
}
div#paginationTop .pages {
float: right;
padding: 5px;
}
div.pagination {
padding: 0px;
margin: 0px;
}
div.pagination a {
padding: 2px 5px 2px 5px;
margin: 2px;
border: 1px solid #8dab68;
text-decoration: none; /* no underline */
color: #5f7f39;
}
div.pagination a:hover, div.pagination a:active {
border: 1px solid #5f7f39;
color: #000;
}
div.pagination span.current {
padding: 2px 5px 2px 5px;
margin: 2px;
border: 1px solid #5f7f39;
font-weight: bold;
background-color: #5f7f39;
color: #FFF;
}
div.pagination span.disabled {
padding: 2px 5px 2px 5px;
margin: 2px;
border: 1px solid #EEE;
color: #DDD;
}
.bold14 {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 14px;
font-weight: bold;
}
.rederror {
color: red;
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack) {
loadList();
}
}
private void loadList()
{
//预设为第1页
int page = 1;
//判断网址後有无参数
//也可用String.IsNullOrWhiteSpace
if (!String.IsNullOrEmpty(Request.QueryString["page"])) {
page = Convert.ToInt32(Request.QueryString["page"]);
}
//设定页面参数属性
//设定控制项参数: 一页几笔资料
WebUserControl_Page.limit = 5;
//设定控制项参数: 作用页面完整网页名称
WebUserControl_Page.targetPage = "WebForm1.aspx";
//建立计算分页资料显示逻辑 (每一页是从第几笔开始到第几笔结束)
//计算每个分页的第几笔到第几笔
var floor = (page - 1) * WebUserControl_Page.limit + 1; //每页的第一笔
var ceiling = page * WebUserControl_Page.limit; //每页的最末笔
//将取得的资料数设定给参数 count
int count = 36; //总资料数,可修改数字测试分页功能是否正常
//设定控制项参数: 总共几笔资料
WebUserControl_Page.totalItems = count;
//渲染分页控制项
WebUserControl_Page.showPageControls();
//设定模拟资料内容
StringBuilder listHtml = new StringBuilder();
for (int i = floor; i <= ceiling; i++) {
if (i <= count) {
listHtml.Append($"<a href=''> --------- 第 {i} 笔资料 --------- </a></li><br /><br />");
}
}
LiteralTest.Text = listHtml.ToString();
}
📢 今天制作的分页控制项逻辑,因为还有隐藏过多页面的功能,原本参考的程序码有奇怪的数字计算在控制,但因为没有解释数字计算的意义,所以看不懂原理,反覆修改数字测试後,将奇怪的数字计算整理,并拉出逻辑判断共用参数将计算过程合理化为自己能理解的模式,由於过程较复杂,在程序码内放了大量的注解解释,希望大家可以理解。
<<: 从零开始的8-bit迷宫探险【Level 24】谁才是高玩?纪录本机最高得分
Let's Start From Scratch 本系列文章的头几篇我决定还是带点基础的东西,但是我...
转换操作符 map/mapError map操作符会执行给定的闭包,将上游发布的内容进行转换,然後再...
在一个电信行业的技术词汇,它是指为了向用户提供(新)服务的准备和安装一个网络的处理过程。它也包括改变...
最後云端,为完赛画下彩虹~~ 为了使部署的云端硬碟能像Google Drive一样使用串流、WebU...
p5 中的 color 物件: 先认识两个色彩学 可以了解 https://www.instagra...