第64章 Jquery JSON Table Nop后台重构定义Jquery DataTables

1 分页操作

    ///<typeparam name="T">泛型类型实例(1个指定类的类型实例)。</typeparam>

    /// <summary>

    /// 【分页列表--接口】

    /// <remarks>

    /// 摘要:

    ///     继承于该接口的具体实现类及其属性成员实例,为1个指定类的数据源执行分页操作提供数据支撑。

    /// </remarks>

    public interface IPagedList<T> : IList<T>

    {

        #region 属性

        /// <summary>

        /// 【页数索引】

        /// <remarks>

        /// 摘要:

        ///     获取分页操作中当前页的页数值。 

        /// </remarks>

        /// </summary>

        int PageIndex { get; }

        /// <summary>

        /// 【页数大小】

        /// <remarks>

        /// 摘要:

        ///     获取分页操作中每页最多显示实例的项(行)数值。 

        /// </remarks>

        /// </summary>

        int PageSize { get; }

        /// <summary>

        /// 【项数总计】

        /// <remarks>

        /// 摘要:

        ///     获取分页操作中数据源实例的项(行)数总计值。 

        /// </remarks>

        /// </summary>

        int TotalCount { get; }

        /// <summary>

        /// 【页数总计】

        /// <remarks>

        /// 摘要:

        ///     获取分页操作中页数总计值。 

        /// </remarks>

        /// </summary>

        int TotalPages { get; }

        /// <summary>

        /// 【有上1页?】

        /// <remarks>

        /// 摘要:

        ///     获取1个值false(没有)/true(有),该值指示在分页操作中当前页是否有上1页(第1页之前没有上1页)。

        /// </remarks>

        /// </summary>

        bool HasPreviousPage { get; }

        /// <summary>

        /// 【有下1页?】

        /// <remarks>

        /// 摘要:

        ///     获取1个值false(没有)/true(有),该值指示在分页操作中当前页是否有下1页(最后1页之后没有下1页)。

        /// </remarks>

        /// </summary>

        bool HasNextPage { get; }

        #endregion

    }

  ///<typeparam name="T">泛型类型实例(1个指定类的类型实例)。</typeparam>

    /// <summary>

    /// 【分页列表--类】

    /// <remarks>

    /// 摘要:

    ///     通过该类及其属性成员实例,为1个指定类的数据源执行分页操作提供数据支撑。

    /// </remarks>

    [Serializable]

    public class PagedList<T> : List<T>, IPagedList<T>

    {

        #region 拷贝构造方法

        /// <param name="source">以列表接口实例进行存储的1个指定类型的数据源(枚举数接口实例=长串型,包含:数组、列表、字典等)。</param>

        /// <param name="pageIndex">分页操作中当前页的页数值。</param>

        /// <param name="pageSize">分页操作中每页最多显示实例的项(行)数值。 </param>

        /// <param name="totalCount">分页操作中实例的项(行)数总计值。</param>

        /// <summary>

        /// 【拷贝构造方法】

        /// <remarks>

        /// 摘要:

        ///     通过拷贝构造方法为该类中的属性成员赋值实例化初始值。

        /// </remarks>

        /// </summary

        public PagedList(IList<T> source, int pageIndex, int pageSize, int? totalCount = null)

        {

            //分页操作中每页最多显示实例的项(行)数值,“Math.Max”方法保证该参数实例的最小值必须>=1。

            pageSize = Math.Max(pageSize, 1);

            TotalCount = totalCount ?? source.Count;

            TotalPages = TotalCount / pageSize;

            if (TotalCount % pageSize > 0)

                TotalPages++;

            PageSize = pageSize;

            PageIndex = pageIndex;

            //该方法主要功能是只从数据源中加载1页数据,以最的小内存开销,为页面的渲染显示提供相应数据支撑,在当前类中基本没有起到应用的作用;真正起到应有作用的是定义在“PagedListExtension(AsyncIQueryableExtensions).ToPagedList”方法中的该方法。

            AddRange(totalCount != null ? source : source.Skip(pageIndex * pageSize).Take(pageSize));

        }

        #endregion

        #region 属性

        /// <summary>

        /// 【页数索引】

        /// <remarks>

        /// 摘要:

        ///     获取分页操作中当前页的页数值。 

        /// </remarks>

        /// </summary>

        public int PageIndex { get; }

        /// <summary>

        /// 【页数大小】

        /// <remarks>

        /// 摘要:

        ///     获取分页操作中每页最多显示实例的项(行)数值。 

        /// </remarks>

        /// </summary>

        public int PageSize { get; }

        /// <summary>

        /// 【项数总计】

        /// <remarks>

        /// 摘要:

        ///     获取分页操作中数据源实例的项(行)数总计值。 

        /// </remarks>

        /// </summary>

        public int TotalCount { get; }

        /// <summary>

        /// 【页数总计】

        /// <remarks>

        /// 摘要:

        ///     获取分页操作中页数总计值。 

        /// </remarks>

        /// </summary>

        public int TotalPages { get; }

        /// <summary>

        /// 【有上1页?】

        /// <remarks>

        /// 摘要:

        ///     获取1个值false(没有)/true(有),该值指示在分页操作中当前页是否有上1页(第1页之前没有上1页)。

        /// </remarks>

        /// </summary>

        public bool HasPreviousPage => PageIndex > 0;

        /// <summary>

        /// 【有下1页?】

        /// <remarks>

        /// 摘要:

        ///     获取1个值false(没有)/true(有),该值指示在分页操作中当前页是否有下1页(最后1页之后没有下1页)。

        /// </remarks>

        /// </summary>

        public bool HasNextPage => PageIndex + 1 < TotalPages;

        #endregion

}

public static class PagedListExtension

    {

        /// <param name="source">以可查询类型接口实例进行存储的1个指定类型的数据源(枚举数接口实例=长串型,包含:数组、列表、字典等)。</param>

        /// <param name="pageIndex">分页操作中当前页的页数值。</param>

        /// <param name="pageSize">分页操作中每页最多显示实例的项(行)数值。 </param>

        /// <param name="getOnlyTotalCount">指示是否只从数据源中加载1页数据,以最的小内存开销,为页面的渲染显示提供相应数据支撑,默认值:false,即只从数据源中加载1页数据</param>

        /// <summary>

        /// 【到分页列表】

        /// <remarks>

        /// 摘要:

        ///     该方法默认只从数据源中加载1页数据,存储到“PagedList”类的实例中,从而实现“PagedList”类实例以最的小内存开销,为页面的渲染显示提供相应数据支撑。

        /// </remarks>

        /// </summary

        public static IPagedList<T> ToPagedList<T>(this IQueryable<T> source, int pageIndex, int pageSize, bool getOnlyTotalCount = false)

        {

            if (source == null)

                return new PagedList<T>(new List<T>(), pageIndex, pageSize);

            //分页操作中每页最多显示实例的项(行)数值,“Math.Max”方法保证该参数实例的最小值必须>=1。

            pageSize = Math.Max(pageSize, 1);

            var count = source.Count();

            var data = new List<T>();

            //通过参数实例的默认值,“AddRange”方法主要功能是只从数据源中加载1页数据,以最的小内存开销,为页面的渲染显示提供相应数据支撑,在当方法中“AddRange”方法起到了自己应用的作用。

            if (!getOnlyTotalCount)

                data.AddRange(source.Skip(pageIndex * pageSize).Take(pageSize).ToList());

            return new PagedList<T>(data, pageIndex, pageSize, count);

        }

    }

2 模型定义

/// <summary>

    /// 【基本查询模型--纪录】

    /// <remarks>

    /// 摘要:

    ///     通过该类及其属性成员实例实现当前程序与前台Jquery DataTabes插件的数据交互操作及其控件和渲染(显示)。

///  注意:

///      该纪录是抽象纪录,所以该纪录只能被其它纪录所继承,并由继承纪录所实例化。

    /// </remarks>

    /// </summary>

    public abstract record BaseSearchModel

    {

        #region 拷贝构造方法

        /// <summary>

        /// 【拷贝构造方法】

        /// <remarks>

        /// 摘要:

        ///     通过拷贝构造方法为该类中的属性成员赋值实例化初始值。

        /// </remarks>

        /// </summary

        protected BaseSearchModel()

        {

            //设置Jquery DataTable插件每页最多的行数(默认值):15,Length>=1。 

            Length = 10;

        }

        #endregion

        #region 属性

        /// <summary>

        /// 【页数】

        /// <remarks>

        /// 摘要:

        ///     获取query DataTable插件当前显示页面的页数值(Jquery DataTable插件默认开始页为:0;而该属性实例则把该默认开始页设置为:1,如果使用默认Jquery DataTable插件,则插件最后页会现“没有匹配结果”异常,即Jquery DataTable插件会多出1页)。

        /// </remarks>

        /// </summary>

        public int Page => (Start / Length) + 1;

        /// <summary>

        /// 【页面大小】

        /// <remarks>

        /// 摘要:

        ///     获取Jquery DataTable插件每页最多的行数值:(默认值)15,PageSize>=1。 

        /// 注意:

        ///     该属性为只读属性,该属性的实例值由该类中“Length”属性成员所决定。

        /// </remarks>

        /// </summary>

        public int PageSize => Length;

        /// <summary>

        /// 【有效页面大小】

        /// <remarks>

        /// 摘要:

        ///     获取/设置Jquery DataTable插件以供选择的每页最多显示的行数值,PageSize或Length:(弹出窗口默认值)7, (默认值)15, 20, 50, 100。 

        /// </remarks>

        /// </summary>

        public string AvailablePageSizes { get; set; }

        /// <summary>

        /// 【绘制】

        /// <remarks>

        /// 摘要:

        ///     获取/设置的Jquery DataTable插件被操作的次数值。

        /// </remarks>

        /// </summary>

        public string Draw { get; set; }

        /// <summary>

        /// 【开始】

        /// <remarks>

        /// 摘要:

        ///     获取/设置Jquery DataTable插件当前显示页面,需要跳过的行数值:=(页数-1)*PageSize(或Length:(弹出窗口默认值)7, (默认值)15, 20, 50, 100),Start>=0。 

        /// </remarks>

        /// </summary>

        public int Start { get; set; }

        /// <summary>

        /// 【长度】

        /// <remarks>

        /// 摘要:

        ///     获取/设置Jquery DataTable插件每页最多的行数值:(默认值)15,Length>=1。 

        /// </remarks>

        /// </summary>

        public int Length { get; set; }

        #endregion

        #region 方法

        /// <summary>

        /// 【设置网格页大小】

        /// <remarks>

        /// 摘要:

        ///    通过以供选择的每页最多显示的行数值,动态设置Jquery DataTable插件每页最多显示行数。

        /// </remarks>

        /// </summary>

        public void SetGridPageSize()

        {

            SetGridPageSize(15, "7, 15, 20, 50, 100");

        }

        /// <summary>

        /// 【设置弹出网格页大小】

        /// <remarks>

        /// 摘要:

        ///    通过以供选择的每页最多显示的行数值,动态设置Jquery DataTable插件每页最多显示行数。

        /// </remarks>

        /// </summary>

        public void SetPopupGridPageSize()

        {

            SetGridPageSize(7, "7, 15, 20, 50, 100");

        }

        ///<param name="pageSize">Jquery DataTable插件每页最多显示行数值。</param>

        ///<param name="availablePageSizes">A以供选择的每页最多显示的行数值。</param>

        /// <summary>

        /// 【设置网格页大小】

        /// <remarks>

        /// 摘要:

        ///    通过以供选择的每页最多显示的行数值,动态设置Jquery DataTable插件每页最多显示行数。

        /// </remarks>

        /// </summary>

        public void SetGridPageSize(int pageSize, string availablePageSizes = null)

        {

            if (availablePageSizes == null)

                availablePageSizes = "7, 15, 20, 50, 100";

            Start = 0;

            Length = pageSize;

            AvailablePageSizes = availablePageSizes;

        }

        #endregion

    }

public record StudentSearchModel : BaseSearchModel

    {

        #region 属性

        /// <summary>

        /// 【姓名】

        /// <remarks>

        /// 摘要:

        ///     获取/设置查询模型类1个指定实例的学生姓名。

        /// </remarks>

        /// </summary>

        [Display(Name = "姓名")]

        public string StudnetName { get; set; }

        #endregion

}

///<typeparam name="T">泛型类型实例(1个指定类的类型实例)。</typeparam>

    /// <summary>

    /// 【基本分页列表--纪录】

    /// <remarks>

    /// 摘要:

    ///     该类及其属性成员实例,为Jquery DataTable插件渲染显示提供基本且必须的数据支撑。

    ///  注意:

    ///     该纪录是抽象纪录,所以该纪录只能被其它纪录所继承,并由继承纪录所实例化。

    /// </remarks>

    public abstract record BasePagedListModel<T>

    {

        #region 属性--Jquery DataTable插件

        /// <summary>

        /// 【数据】

        /// <remarks>

        /// 摘要:

        ///     获取/设置以枚举数接口进行存储的学生实体的所有实例。

        /// 注意:

        ///     为了与Jquery DataTable插件能够在浏览器中渲染出这些数据,该属性必须被命名为“Data”,也只能被命名为“Data”,否则浏览器中将不会渲染出这些数据。

        /// </remarks>

        /// </summary>

        public IEnumerable<T> Data { get; set; }

        /// <summary>

        /// 【绘制】

        /// <remarks>

        /// 摘要:

        ///     获取/设置1个指定的Jquery DataTable插件被操作的次数值。

        /// 注意:

        ///     C#中的属性命名通过使用“骆驼命名方式”,而JSON编码格式中的键(key)命名的第1个字母必须是小写,否则浏览器中将不会通过Jquery DataTable插件渲染出这些数据。

        ///  由于上述原因就必须使用“[JsonProperty(PropertyName = "xxx")]”标记把C#中的属性名序列化为符合JSON编码格式中的键(key)命名。

        /// </remarks>

        /// </summary>

        [JsonProperty(PropertyName = "draw")]

        public string Draw { get; set; }

        /// <summary>

        /// 【过滤总计】

        /// <remarks>

        /// 摘要:

        ///     获取/设置符合指定过滤条件的1个指定实体所有实例的总计值。

        /// 注意:

        ///     C#中的属性命名通过使用“骆驼命名方式”,而JSON编码格式中的键(key)命名的第1个字母必须是小写,否则浏览器中将不会通过Jquery DataTable插件渲染出这些数据。

        ///  由于上述原因就必须使用“[JsonProperty(PropertyName = "xxx")]”标记把C#中的属性名序列化为符合JSON编码格式中的键(key)命名。

        /// </remarks>

        /// </summary>

        [JsonProperty(PropertyName = "recordsFiltered")]

        public int RecordsFiltered { get; set; }

        /// <summary>

        /// 【总计】

        /// <remarks>

        /// 摘要:

        ///     获取/设置1个指定实体所有实例的总计值。

        /// 注意:

        ///     C#中的属性命名通过使用“骆驼命名方式”,而JSON编码格式中的键(key)命名的第1个字母必须是小写,否则浏览器中将不会通过Jquery DataTable插件渲染出这些数据。

        ///  由于上述原因就必须使用“[JsonProperty(PropertyName = "xxx")]”标记把C#中的属性名序列化为符合JSON编码格式中的键(key)命名。

        /// </remarks>

        /// </summary>

        [JsonProperty(PropertyName = "recordsTotal")]

        public int RecordsTotal { get; set; }

        #endregion

    }

/// <summary>

    /// 【学生分页列表--纪录】

    /// <remarks>

    /// 摘要:

    ///     该类及其属性成员实例,加载学生实体的所有实例,为Jquery DataTable插件渲染显示提供必须的数据支撑。

    /// </remarks>

    public record StudentPagedListModel : BasePagedListModel<Student>

    {

    }

3 JqueryDataTable.cshtml

@model JsonTable.Nop.Models.StudentSearchModel

@{

    ViewData["Title"] = "JqueryDataTable";

}

@section styles

{

    <link rel="stylesheet" type="text/css" href="~/lib/dataTables-1.12.1/css/dataTables.bootstrap5.css" />

}

<div class="row">

    <div class="col-md-12 mt-5">

            <form asp-controller="Nop" asp-action="JqueryDataTable" method="post" class="row gx-3 gy-2 align-items-center" id="JqueryDataTableForm">

            <div asp-validation-summary="ModelOnly"></div>

            <div class="col-sm-3">

                <label asp-for="StudnetName" class="visually-hidden"></label>

                <input asp-for="StudnetName" class="form-control" />

                <span asp-validation-for="StudnetName" class="text-danger"></span>

            </div>

            <div class="col-sm-9">

                <button type="button" id="searchStudent" class="btn btn-primary me-3">

                    <i class="fas fa-search"></i>

                    查询

                </button>

            </div>

        </form>

    </div>

</div>

<div class="row">

    <div class="col-md-12 mt-5">

        <table id="example" class="table table-striped table-bordered dt-responsive nowrap" width="100%" cellspacing="0">

        </table>

    </div>

</div>

@section Scripts {

    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}

    <script type="text/javascript" src="~/lib/dataTables-1.12.1/js/jquery.dataTables.js"></script>

    <script type="text/javascript" src="~/lib/dataTables-1.12.1/js/dataTables.bootstrap5.js"></script>

    <script type="text/javascript">

        var tableModel;

        $(document).ready(function () {

            tableModel = $("#example").DataTable({

                language: {

                    url: '../../lib/dataTables-1.12.1/language/zh.json' //DataTables语言配置选项

                },

                processing: true//是否显示“处理中...”(排序的时候,数据很多耗费时间长的话,也会显示这个)

                serverSide: true//是否开启服务器模式

                paging: true, //是否允许翻页

                //"rowId": "userId", //指定用于行ID的属性名 默认是:DT_RowId

                lengthMenu: [7, 15, 20, 50, 100], //DataTableJquery插件下拉框控件中的数量选择内容。

                pageLength: 15, // 每页的行数的默认值:10。

                searching: true, //是否在DataTableJquery插件中显示搜索框控件。

                autoWidth: true,   //自适应宽度

                //bSort : false, //禁止排序

                pagingType: "numbers",//使用该类型,为在“表中数据为空”时,禁止在DataTableJquery插件中,显示“上页”、“下页”按钮。

                order: [[1, "desc"]],//默认设置第二列以“倒序”方式对DataTableJquery插件进行排序显示。

                ajax: {

                    url: "/Nop/PrepareJquerySearch",

                    type: "POST",

                    datatype: "JSON",

                    cache: false//禁用缓存

                    data: function (studentSearchModel) { //传递参数

                        studentSearchModel.studnetName = $("#StudnetName").val();

                    },

                },

                columnDefs: [{  //设置列定义初始化属性

                    "defaultContent": "", //为列设置默认的静态内容

                    "targets": "_all"  //指定所有列

                }],

                //注意:"data"对应的字段(实体属性)的第1个字母必是小写,否则实体实例的值将不会被浏览器渲染出来。

                "columns": [

                    {

                        "orderable": false,//禁用DataTableJquery插件第1列中的“排序”按钮。

                        "data": "id", "title": "<input type='checkbox' id='checkAll' class='form-check-input checkBox25' />",

                        "render": function (data, type, row, meta) {

                            return "<input type='checkbox' name='checkItem' value=" + data + " class='form-check-input checkBox25' />";

                        },

                        "sWidth": "25px",

                    },

                    { "data": "id", "name": "id", "title": "编号", "autoWidth": true },//“name”属性及其对应值对DataTableJquery插件进行排序操作。

                    { "data": "code", "name": "code", "title": "学号", "autoWidth": true },//“name”属性及其对应值对DataTableJquery插件进行排序操作。

                    { "data": "studnetName", "name": "studnetName", "title": "姓名", "autoWidth": true },//“name”属性及其对应值对DataTableJquery插件进行排序操作。

                    { "data": "specialty", "name": "specialty", "title": "专业", "autoWidth": true },//“name”属性及其对应值对DataTableJquery插件进行排序操作。

                    { "data": "grade", "name": "grade", "title": "年级", "autoWidth": true },//“name”属性及其对应值对DataTableJquery插件进行排序操作。

                    { "data": "category", "name": "category", "title": "班级", "autoWidth": true },//“name”属性及其对应值对DataTableJquery插件进行排序操作。

                    {

                        "orderable": false,//禁用DataTableJquery插件第8列中的“排序”按钮。

                        "render": function (data, type, full, meta) {

                            //注意:“,500,500,true”参数实例中的“,”之间不能存在空格,否则“编辑”按钮点击无效,即“编辑”弹出窗口将不会出现。

                            return "<a href='#' class='btn btn-info' >编辑</a>";

                        },

                        "sWidth": "30px",

                    },

                    {

                        "orderable": false,//禁用DataTableJquery插件第9列中的“排序”按钮。

                        data: null,

                        render: function (data, type, row) {

                            return "<a href='#' class='btn btn-danger'>删除</a>";

                        },

                        "sWidth": "30px",

                    },

                ],

            });

            // init:初始化和数据都加载完成,和 initComplete配置等价

            tableModel.on("draw", function () {

                $("#checkAll").prop("checked", false);//每次翻页;或跳转到上一页;或跳转到指定,DataTableJquery插件中已经处于全选状态的全选复选框控件,处于不选中状态。

                //全选

                $("#checkAll").click(function () {

                    $("[name=checkItem]:checkbox").prop("checked", this.checked);

                });

                //复选框组的联动效果

                $("[name=checkItem]:checkbox").click(function () {

                    var flag = true;

                    $("[name=checkItem]:checkbox").each(function (index) {

                        if (!this.checked) {

                            flag = false;

                        }

                    });

                    $("#checkAll").prop("checked", flag);

                });

            });

        });

        //查询列表

        $("#searchStudent").on("click", function () {

            //重新加载DataTable插件,并返回第1页。

            $("#example").DataTable().ajax.reload();

        });

    </script>


}

 

对以上功能更为具体实现和注释见:22-08-19-064_JsonTable(Nop后台重构定义Jquery DataTables)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值