自定义TageHelper并不难,只要记住几个点:
- 继承TagHelper
- 定义需要在TagHelper中传入的参数,如果不需要参数,可忽略
- 重写Process方法
- 在Process中拼接要输出的HTML字符串
- 在Views > _ViewImports.cshtml 中添加引用
仅此五步即可。
接下来实现分页。这里要做的是一个像bootstrap一样的简单分页
页面元素包括:首页链接 页码链接 尾页链接,也就是几个<a>标签,很简单,代码实现也就需要下面几步:
- 定义必要参数:记录总数 total,当前页码 pageIndex,每页显示的条数 pageSize,链接地址(不带分页参数)routeUrl
- 计算总页数 pageCount
- 拼接HTML字符串
当然,一个可用的连接必然还要考虑到两个基本功能:
- 跳转时保留查询参数
- 如果页数很多,全部显示必然会破坏页面结构,所以只能显示当前页码周围固定数量的页码,而隐藏其他的页码。
OK,下面是具体的代码实现:
using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Project.TagHelpers
{
public class MyPagerTagHelper : TagHelper
{
/// <summary>
/// 数据总数
/// </summary>
public int Total { get; set; } = 0;
/// <summary>
/// 当前页码
/// </summary>
public int PageIndex { get; set; } = 1;
/// <summary>
/// 每页记录数
/// </summary>
public int PageSize { get; set; } = 20;
/// <summary>
/// 当前页路由
/// </summary>
public string RouteUrl { get; set; }
/// <summary>
/// 当前页的查询条件
/// </summary>
public string Query { get; set; }
private string SetQueryString()
{
var result = new List<string>();
if (!string.IsNullOrWhiteSpace(Query))
{
if (Query.StartsWith("?"))
{
Query = Query.Remove(0, 1);
}
string[] paramList = Query.Split('&');
foreach (var param in paramList)
{
var paramName = param.Trim().ToLower();
if (!paramName.StartsWith("pageindex=") && !paramName.StartsWith("pagesize="))
{
result.Add(param);
}
}
// 用LINQ遍历
// result = paramList.Where(p => !p.ToLower().StartsWith("pageindex=") && !p.ToLower().StartsWith("pagesize=")).ToList();
}
result.Add("pageIndex={0}");
result.Add("pageSize=" + PageSize.ToString());
return "?" + string.Join('&', result);
}
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "div";
output.Attributes.Add("class", "my-pager");
if (PageSize <= 0) { PageSize = 20; }
if (PageIndex <= 0) { PageIndex = 1; }
if (Total <= 0) { return; }
//总页数
var totalPage = Total / PageSize + (Total % PageSize > 0 ? 1 : 0);
if (totalPage <= 0) { return; }
Query = SetQueryString();
//构造分页样式
var sbPage = new StringBuilder(string.Empty);
sbPage.Append("<ul class=\"pagination\">");
sbPage.AppendFormat("<li><a href=\"{0}{1}\">首页</a></li>",
RouteUrl,
string.Format(Query, 1)
);
// 计算显示的页码
int start = 1;
int end = totalPage;
bool hasStart = false;
bool hasEnd = false;
if (totalPage > 10)
{
if (PageIndex > 5)
{
start = PageIndex - 4;
hasStart = true;
}
if (start + 9 < totalPage)
{
end = start + 9;
hasEnd = true;
}
else
{
end = totalPage;
start = totalPage - 9;
}
}
if (hasStart)
{
sbPage.AppendFormat("<li><a href=\"{0}{1}\">...</a></li>",
RouteUrl,
string.Format(Query, start - 1)
);
}
for (int i = start; i <= end; i++)
{
sbPage.AppendFormat("<li {1}><a href=\"{2}{3}\">{0}</a></li>",
i,
i == PageIndex ? "class=\"active\"" : "",
RouteUrl,
string.Format(Query, i)
);
}
if (hasEnd)
{
sbPage.AppendFormat("<li><a href=\"{0}{1}\">...</a></li>",
RouteUrl,
string.Format(Query, end + 1)
);
}
sbPage.Append("<li>");
sbPage.AppendFormat("<a href=\"{0}{1}\">",
RouteUrl,
string.Format(Query, totalPage));
sbPage.Append("尾页");
sbPage.Append("</a>");
sbPage.Append("</li>");
sbPage.Append("</ul>");
output.Content.SetHtmlContent(sbPage.ToString());
}
}
}
话说,这不是一个令人满意的实现,特别是对查询字符串的处理上,不过此分页方案最终被放弃,也就没有继续深入,只提供思路,如有更好的实现方法,请留言告知,不胜感激。
接下来,在Views > _ViewImports.cshtml 中插入代码
@using Project.TagHelpers
@addTagHelper *, Project.TagHelpers
至此,自定义分页TageHelper完成,页面中调用方法如下:
<my-pager total="@Model.RecordCount"
page-index="@Model.PageIndex"
page-size="@Model.PageSize"
route-url="/Admin/WxAccount/Index"
query="@Url.ActionContext.HttpContext.Request.QueryString">
</my-pager>
@Model.xxx是我通过Controller传入的视图的数据,调用时请按实际情况替换即可。
结束,谢谢~