0

我正在 MVC 4 中为 jqGrid 实现服务器端分页和排序。我将视图模型对象作为 postData 传递给 jqGrid url 操作方法。看看网格定义。

var isGridDefined = false;
$(document).ready(function () {
    function DefineGrid(Year, Month) {
        var mygrid = $("#RptUpload");
        mygrid.jqGrid({
            loadonce: false,
            async: false,
            datatype: 'json',
            postData: { bReload: true, Year: Year, Month: Month },
            url: '@Url.Action("DMEUploadDetailsList", "Reports")',
            jsonReader: { repeatitems: false, root: "DataRows" },
            colNames: ['@VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_OrderID',
                        '@VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_CompanyName',
                        '@VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_PatientID',
                        '@VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_PatientName',
                        "@VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_DOB",
                        '@VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_Insurance',
                        "@VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_UploadDate"
            ],
            colModel: [
                { name: 'ReadingID', index: 'ReadingID', width: 55, fixed: true, sorttype: 'integer', align: 'center' },
                {
                    name: 'CompanyName', index: 'CompanyName', align: 'center', width: 200,
                    cellattr: function (rowId, tv, rawObject, cm, rdata) { return 'style="white-space: normal!important;' },
                },
                { name: 'PatientID', index: 'PatientID', width: 55, fixed: true, sorttype: 'integer', align: 'center' },
                {
                    name: 'PatientName', index: 'PatientName', align: 'center', width: 200,
                    cellattr: function (rowId, tv, rawObject, cm, rdata) { return 'style="white-space: normal!important;' },
                },
                {
                    name: 'DOB', index: 'DOB', width: 80, fixed: true, sorttype: 'date', formatter: 'date', formatoptions: { srcformat: 'm/d/Y', newformat: 'm/d/Y' },
                    align: 'center'
                },
                { name: 'InsuranceType', index: 'InsuranceType', align: 'center', width: 150, cellattr: function (rowId, tv, rawObject, cm, rdata) { return 'style="white-space: normal!important;' }, },
                {
                    name: 'UploadDate', index: 'UploadDate', width: 80, fixed: true, sorttype: 'date', formatter: 'date', formatoptions: { srcformat: 'm/d/Y', newformat: 'm/d/Y' },
                    align: 'center'
                }
            ],
            rowNum: 20,
            rowList: [20, 50, 100, 200],
            pager: '#UploadPager',
            caption: '@VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_Title',
            viewrecords: true,
            height: 'auto',
            width: 770,
            hidegrid: false,
            shrinkToFit: true,
            scrollOffset: 0,
            headertitles: true,
            loadError: function (xhr, status, error) {
                alert(status + " " + error);
            },
            //onPaging: function (pgButton) {
            //    $("#RptUpload").jqGrid("setGridParam", { postData: { bReload: false } });
            //},
            loadCompete: function () {
                $("#RptUpload").jqGrid("setGridParam", { datatype: 'json', postData: { bReload: false } });
            }
        });
        mygrid.navGrid('#UploadPager', { edit: false, add: false, del: false, search: false, refresh: false });
        isGridDefined = true;
    }

    $("#rptRefresh").click(function (e) {
        e.preventDefault();
        var Form = $("form[id='FrmDMEUploadDetails']");
        Form.validate();
        if (Form.valid()) {
            RemoveValidatioMessages();
            $("#gridContainer").show();
            var Year = $("#Year").val();
            var Month = $("#Month").val();
            if (!isGridDefined)
                DefineGrid(Year, Month);
            else
                $("#RptUpload").jqGrid("setGridParam", { datatype: "json", page: 1, postData: { bReload: true, Year: Year, Month: Month } }).trigger("reloadGrid");
        }
        else {
            $("#RptUpload").clearGridData();
            $("#gridContainer").hide();
        }
        $(".chzn-select-deselect").trigger("liszt:updated");
        return false;
    });
});

&我的操作方法如下

public ActionResult DMEUploadDetailsList(bool bReload, string Year, string Month, string nd, int rows, int page, string sidx, string sord, string filters)
    {
        DataSet SearchResult = null;
        List<ReportData> ResultRows = new List<ReportData>();
        JQGridResult Result = new JQGridResult();
        if (bReload)
        {
            SearchResult = DB.ExecuteDataset("ConnectionString", "pc_GetUploadDetail",
                                            new SqlParameter("@Year", Year),
                                            new SqlParameter("@Month", Month));

            Common.SetSession(SearchResult, null, "DMEUploadByMonth");
        }
        else
            SearchResult = SessionManager.GetSession().GetAttribute("DMEUploadByMonth") as DataSet;

        if (SearchResult != null)
        {
            DataTable dtSearchResult = SearchResult.Tables[0];

            # region Handle server side Filtering, sorting and paging
            int totalRecords = dtSearchResult.Rows.Count; //before paging
            int totalPages = (int)Math.Ceiling((decimal)totalRecords / (decimal)rows); //--- number of pages
            int startIndex = ((page > 0 ? page - 1 : 0) * rows);
            if (sidx != "")
            {
                dtSearchResult.DefaultView.Sort = sidx + " " + sord;
                dtSearchResult = dtSearchResult.DefaultView.ToTable();
            }
            # endregion

            for (int i = startIndex; i < dtSearchResult.Rows.Count; i++)
            {
                ResultRows.Add(new ReportData()
                {
                    ReadingID = Convert.ToInt32(dtSearchResult.Rows[i][0]),
                    CompanyName = Convert.ToString(dtSearchResult.Rows[i][1]),
                    PatientID = Convert.ToInt32(dtSearchResult.Rows[i][2]),
                    PatientName = Convert.ToString(dtSearchResult.Rows[i][3]),
                    DOB = (dtSearchResult.Rows[i][4] != DBNull.Value ? Convert.ToDateTime(dtSearchResult.Rows[i][4]) : (DateTime?)null),
                    InsuranceType = Convert.ToString(dtSearchResult.Rows[i][5]),
                    UploadDate = (dtSearchResult.Rows[i][6] != DBNull.Value ? Convert.ToDateTime(dtSearchResult.Rows[i][6]) : (DateTime?)null)
                });
                if (ResultRows.Count == rows) break;
            }
            Result.DataRows = ResultRows;
            Result.page = page;
            Result.total = totalPages;
            Result.records = totalRecords;
        }
        return Json(Result, JsonRequestBehavior.AllowGet);
    }

当前实现的问题是我的操作方法DMEUploadDetailsList没有被调用,尽管视图模型对象被成功传递给请求。&当使用客户端分页和排序时,此实现工作正常。如果我遗漏任何内容或纠正我的错误以使服务器端分页和排序正常工作,请建议我。

此网格在刷新按钮上定义或重新加载。现在我想要确定是否在刷新按钮单击或分页和排序操作时调用动作方法?

[现在我想描述问题陈述的最后两句话。它指定当我的页面加载时未定义网格。一旦我选择过滤器并单击刷新按钮,我的网格就被定义为第一次并重新加载以供后续单击刷新。如果您浏览操作方法代码,您会看到我正在尝试使用 bReload 位变量,当它为真时 [如果单击刷新按钮] 我想从 SQL 查询数据,否则从存储在会话中的数据集中分页或排序请求的情况]。现在,如果您查看定义或重新加载调用中的 postData 参数,我将 breload 传递为 true。当用户请求排序和分页时,我不知道如何将此参数覆盖为 false。

4

2 回答 2

1

抱歉,但我在您的代码中没有看到任何分页实现。您计算需要跳过的记录数并将其保存在 中startIndex,但以后不要使用startIndex。您当前的代码只是从表中获取数据DataTable并返回所有项目。您需要跳过startIndex项目。例如,您可以从而不是开始for循环。i = startIndexi = 0

一般来说,像答案中描述的那样构造使用构造或使用存储过程的SELECT语句会更有效(也请参见另一个答案)。以这种方式,您的服务器代码将从 SQL 服务器仅获取一页数据,而不是获取所有数据记录并仅返回一页。SqlCommandTOP

更新:我会将您的客户端代码重写为以下内容

$(document).ready(function () {
    var templateDate = {
            width: 80,
            fixed: true,
            sorttype: "date",
            formatter: "date",
            formatoptions: { srcformat: "m/d/Y", newformat: "m/d/Y" }
        },
        templateInt = { width: 55, fixed: true, sorttype: "integer" },
        templateText = {
            width: 200,
            cellattr: function () {
                return 'style="white-space: normal!important;'
            }
        },
        mygrid = $("#RptUpload");

    // create the grid without filling it (datatype: "local")
    mygrid.jqGrid({
        datatype: "local", // to revent initial loading of the grid
        postData: {
            bReload: true,
            Year: function () { return $("#Year").val(); },
            Month: function () { return $("#Month").val(); }
        },
        url: '@Url.Action("DMEUploadDetailsList", "Reports")',
        jsonReader: { repeatitems: false, root: "DataRows" },
        colNames: [ "@VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_OrderID",
                    "@VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_CompanyName",
                    "@VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_PatientID",
                    "@VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_PatientName",
                    "@VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_DOB",
                    "@VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_Insurance",
                    "@VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_UploadDate"
        ],
        colModel: [
            { name: "ReadingID", template: templateInt },
            { name: "CompanyName", template: templateText },
            { name: "PatientID", template: templateInt },
            { name: "PatientName", template: templateText },
            { name: "DOB", template: templateDate },
            { name: "InsuranceType", width: 150, template: templateText },
            { name: "UploadDate", template: templateDate }
        ],
        cmTemplate: { align: "center" },
        rowNum: 20,
        rowList: [20, 50, 100, 200],
        pager: "#UploadPager",
        caption: "@VirtuOxAdmin.DMEUploadDetails_Grid_RptUpload_Title",
        viewrecords: true,
        height: "auto",
        width: 770,
        hidegrid: false,
        headertitles: true,
        loadError: function (xhr, status, error) {
            alert(status + " " + error);
        }
    });
    mygrid.navGrid("#UploadPager",
        { edit: false, add: false, del: false, search: false, refresh: false });
    mygrid.closest(".ui-jqgrid").hide(); // hide the grid

    $("#rptRefresh").click(function (e) {
        var Form = $("form[id=FrmDMEUploadDetails]");
        e.preventDefault();
        Form.validate();
        if (Form.valid()) {
            RemoveValidatioMessages();
            mygrid.jqGrid("setGridParam", { datatype: "json" })
                .trigger("reloadGrid", [{page: 1}])
                .closest(".ui-jqgrid").show(); // show the grid;
        } else {
            mygrid.clearGridData();
            mygrid.closest(".ui-jqgrid").hide(); // hide the grid
        }
        $(".chzn-select-deselect").trigger("liszt:updated");
        return false;
    });
});

网格将使用 创建datatype: "local",因此urlpostData将被忽略。在那之后,在我看来,似乎不需要在服务器端使用bReload属性。postData尽管如此,我bReload仍将其包含在 JavaScript 代码中,直到您将其从服务器代码中删除。

此外,我简化了colModel列模板的使用(cmTemplatejqGridtemplate的选项和属性colModel)。有关更多信息,请参阅旧答案。我还删除了 jqGrid 的一些不需要的选项,这些选项的值为默认值(请参阅选项文档中的“默认”列)。

关于新版本存储过程的使用(pc_GetUploadDetail在您的代码中),您可以考虑引入pc_GetUploadDetailPaged支持更多参数的新版本(如)。它不会破坏使用旧过程的现有代码,但您仍然可以在 SQL Server 上使用数据排序和分页,而不是将所有查询结果获取到 Web 服务器并在 C# 中实现排序和分页。

于 2013-10-14T18:45:05.103 回答
0

我通过在 jqGrid 定义和重新加载调用中删除 Form.serialize() 作为 postData 参数解决了我最初的 jqGrid url 没有被调用的问题。此问题与服务器端排序和分页无关。这是由于我之前将 postData 参数定义为 Form.serialize() 造成的。相反,我使用将单个参数传递给 postData 数组。我的下一个问题与服务器端的排序和分页有关。当用户通过网格页面或想要对网格数据进行排序时,我想从会话数据集中获取数据;否则通过查询 SQL 服务器重新加载新数据。根据 Oleg 的回答,我必须采用在 SQL 端而不是在 c# 中进行分页和排序的简化方式。但是我不允许按照 Oleg 的建议添加新版本的存储过程。像这样在网格定义中的operCode 。

 postData: {
            operCode: "Reload",
            Year: function () { return $("#Year").val(); },
            InsuranceID: function () { return $("#InsuranceType").val(); },
            CustomerID: function () { return $("#CompanyName").val(); }
        },

现在我添加了onPaging 和 onSortCol事件来覆盖 operCode postData 参数值,如下所示

onPaging: function (pgButton) {
            mygrid.jqGrid("setGridParam", { datatype: 'json', postData: { operCode: "Paging" } });
        },
        onSortCol: function (index, iCol, sortorder) {
            mygrid.jqGrid("setGridParam", { datatype: 'json', postData: { operCode: "Sorting" } });
        }

现在,每当用户单击刷新按钮时,操作码都会作为重新加载发送,在分页时作为“分页”和在排序时作为“排序”

我的服务器端动作方法代码如下

public ActionResult DMEUploadDetails(string operCode, string Year, string Month, string nd, int rows, int page, string sidx, string sord, string filters)
    {
        DataSet SearchResult = null;
        List<ReportData> ResultRows = new List<ReportData>();
        JQGridResult Result = new JQGridResult();
        if (operCode == "Reload")
        {
            SearchResult = DB.ExecuteDataset("ConnectionString", "pc_GetUploadDetail",
                                            new SqlParameter("@Year", Year),
                                            new SqlParameter("@Month", Month));

            Common.SetSession(SearchResult, null, "POXMonthlyUploads");
        }
        else
            SearchResult = (SessionManager.GetSession().GetAttribute("POXMonthlyUploads") as System.Web.UI.WebControls.GridView).DataSource as DataSet;

        if (SearchResult != null)
        {
            DataTable dtSearchResult = SearchResult.Tables[0];

            # region Handle server side Filtering, sorting and paging
            int totalRecords = dtSearchResult.Rows.Count; //before paging
            int totalPages = (int)Math.Ceiling((decimal)totalRecords / (decimal)rows); //--- number of pages
            int startIndex = ((page > 0 ? page - 1 : 0) * rows);
            if (sidx != "" && operCode == "Sorting")
            {
                dtSearchResult.DefaultView.Sort = sidx + " " + sord;
                dtSearchResult = dtSearchResult.DefaultView.ToTable();
                SearchResult.Tables.RemoveAt(0);
                SearchResult.Tables.Add(dtSearchResult);
                Common.SetSession(SearchResult, null, "POXMonthlyUploads");
            }
            # endregion

            for (int i = startIndex; i < dtSearchResult.Rows.Count; i++)
            {
                ResultRows.Add(new ReportData()
                {
                   //code to fill data to structure object
                });
                if (ResultRows.Count == rows) break;
            }
            Result.DataRows = ResultRows;
            Result.page = page;
            Result.total = totalPages;
            Result.records = totalRecords;
        }
        return Json(Result, JsonRequestBehavior.AllowGet);
    }

非常感谢 Oleg 给了我一些关于 jqGrid 的额外知识并给了我关于服务器端分页和排序的好主意。

于 2013-10-17T11:43:32.930 回答