65.9K
CodeProject 正在变化。 阅读更多。
Home

在 ASP.NET 中使用 JqGrid

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.90/5 (102投票s)

2013 年 6 月 20 日

CPOL

15分钟阅读

viewsIcon

576398

downloadIcon

29754

如何在 ASP.NET 中集成 JqGrid。

引言

大家好,我又回来了,带来了冰山一角。

寻找冰山大小和体积的责任是您的。这次的冰山是 JqGrid。你们可能认为 JqGrid 不是什么新东西,那为什么......对吧?没错,JqGrid 插件不是什么新东西。它在开源世界中是一个经过验证的数据显示控件,并得到 AJAX 的广泛支持。JqGrid 的优点在于其分页、排序、搜索等功能变得简单,并支持 JSON。

那么问题来了,我为什么要写这个...

我之所以撰写这篇文章,是因为我无法在网上找到任何概述 JqGrid 端到端集成的资源。

第二部分JqGrid 行内编辑

让我思考 JqGrid 的问题

我正在开发一个拥有超过两百万用户的应用程序;在该应用程序中,有一个选项可以通过用户的名字、姓氏和 SSN 的最后四位数字搜索用户,我们使用我们的网格视图来显示搜索结果。

随着用户数量的增加,搜索结果也开始急剧增长,我们开始获得更多

相同组合的 300 多个搜索结果。

这使得用户很难找到确切的人或用户。建议的解决方案是在客户端提供更多的过滤或搜索功能。这里出现的下一个问题是,我们如何为现有网格添加这些功能,或者市场上有哪些控件提供这些功能。

这次搜索让我们找到了 JqGrid,它是一个免费控件,拥有所有上述功能,并且只需很少的编码工作即可完成。

关于 JqGrid 的几句话

  • JqGrid 是一个时尚且功能丰富的表格数据呈现控件。
  • JqGrid 是一个用于在 Web 上表示和操作表格数据的 JavaScript 控件。
  • JqGrid 支持 Ajax。
  • JqGrid 可以与任何服务器端技术集成,如 ASP、JavaServelets、JSP、PHP 等。
  • JqGrid 由 Trirand Inc. 的 Tony Tomov 开发。
  • JqGrid 与 ASP.NET 集成非常简单。

JqGrid 与 ASP.NET 集成逐步说明

  • 从源代码下载 JqGrid。
  • 将所需文件添加到 ASP.NET 应用程序(包括脚本和 CSS)。
  • 在所需页面中初始化 JqGrid。
  • 绑定数据。

正如我在第一点中提到的,您可以从 http://www.trirand.com/blog/?page_id=6 下载 JqGrid 和相关文件。

我尝试下载它,得到了一个名为 _jquery.jqGrid-4.5.2.zip_ 的 zip 文件。从 zip 文件的名称本身我就可以看出我下载的是 JqGrid 的 4.5.2 版本。

让我们解压并探索 zip 文件,看看里面都有什么。我发现里面有一些 CSS 文件夹、一些脚本文件夹等。让我们去看看我们可以利用哪些文件。为了让您更好地理解,我创建了一个名为 JQGridDemo 的演示应用程序来展示集成和功能。

我们主要需要的是 jQuery 文件,因为我们的主角依赖于 JavaScript 和 jQuery。

为了保存 JqGrid 相关文件,我在解决方案中创建了一个名为 JQGridReq 的文件夹。作为第一步,我将 jQuery 文件添加进去。

添加了 jQuery 1.9。我认为 1.9 jQuery 是 jQuery 最新的稳定版本。如果我们要使用 jQuery 的任何 UI 相关内容,接下来需要什么?是的,当然是 CSS 文件。但是我在文件夹中搜索了 jQuery CSS 文件,我找不到。没问题...好吧,我们来做一件事,从互联网上浏览并下载。

更好,对吧?

好的,最后我从互联网上找到了。_Jquery-ui-1.9.2.custom.css_,我们把它也添加到我们的应用程序中。请确保您还添加了相应的图像文件夹,因为我们正在添加 CSS,它可能也需要与 CSS 相关的图像。

所以我们现在已经准备好 jQuery 的东西了。

让我们开始逐个添加我们的 JqGrid 文件

  1. jquery.jqGrid-4.5.2\src\ jquery.jqGrid.js
  2. jquery.jqGrid-4.5.2\js\i18n\ grid.locale-en.js
  3. jquery.jqGrid-4.5.2\css\ ui.jqgrid.css

你注意到第二个文件了吗?它非常重要。我们也添加了 CSS 文件。现在我们已经完成了先决条件。您可以在下面的快照中看到我们添加的文件及其文件夹结构。

让我们转到 .aspx 页面来添加 JqGrid。

对于示例项目,我使用了一个简单的员工管理案例研究。从解决方案本身,您可以看出我正在使用母版页。所以我们要做的是,必须在母版页的 HTML 页面的 head 部分中调用所有必需的文件。

您可以在下面的部分中看到我在母版页的头部区域添加了什么。

好的,现在我所做的是,我直接进入我们计划放置 JqGrid 的页面。这里是 _Default.aspx_ 页面。

在该页面内放置了一个 ID 为 jQGridDemo 的 HTML 表格。(这个表格将充当我们的主角 JqGrid。)

我的意图是将表格转换为 JqGrid。这怎么可能呢?你以前使用过 jQuery 中的 Dialog 还是 JSON 吗?

算了...没问题。

我们必须将表初始化为 JqGrid,并包含我们计划在网格中显示的字段。这里我希望显示:

  1. ID
  2. 名字
  3. 姓氏
  4. SSN 后四位
  5. 部门
  6. 年龄
  7. 薪资
  8. 婚姻状况
  9. 地址。

您可以使用以下脚本将表格初始化为网格。

<script type="text/javascript">
    jQuery("#jQGridDemo").jqGrid({
        url: '',
        datatype: "json",
        colNames: ['Id','First Name', 'Last Name', 'Last 4 SSN', 'Department', 
                'Age', 'Salary',  "Address",'Marital Status'],
        colModel: [
        { name: '_id', index: '_id', width: 20, stype: 'text' },
        { name: 'FirstName', index: 'FirstName', width: 150 },
        { name: 'LastName', index: 'LastName', width: 150 },
           { name: 'LastSSN', index: 'LastSSN', width: 100 },
        { name: 'Department', index: 'Department', width: 80, align: "right" },
        { name: 'Age', index: 'Salary', width: 80, align: "right" },
        { name: 'Salary', index: 'Salary', width: 80, align: "right" },
        { name: 'Address', index: 'Address', width: 150, sortable: false },
        { name: 'MaritalStatus', index: 'MaritalStatus', width: 100, sortable: false }
      ],
        rowNum: 10,
        sortname: 'id',
        viewrecords: true,
        sortorder: "desc",
        caption: "List Employee Details"
    });
</script> 

运行应用程序。您将看到一个样式化的网格,如下所示,但没有显示数据。

我想在网格显示后,你可以读懂我在用脚本初始化网格时写了什么,对吗?

colNames 是网格的标题。colModel 属性是一个 JSON 对象数据字段,用于配置网格的每一列。

我可以说它是要在网格中显示的数据模型,就像我们在数据集字段 `name.colNames` 属性中使用的那样,它应该与 colModel 属性中的项匹配。您可能已经注意到 url 属性留空了。为什么?而且您可能也想知道为什么网格中没有显示数据,对吗?对于这两个问题,我只能给您一个答案。那就是为了 AJAX 回调。

我将向您展示网格是如何填充数据的。

为了方便使用,我在这里使用 MongoDB 作为我的后端。这里出现的下一个问题是 URL 如何实现数据目的?

我所做的是,我创建了自定义 HTTP 处理程序,并且 HTTP 处理程序中的函数将获取员工记录并写入 HTTP 响应中。

HTTP 响应将是上述格式的 JSON 字符串。我们的 JqGrid 读取 JSON 响应,并借助前面提到的 colMode 在 JqGrid 中显示。您需要注意的一点是,我们现在正在处理 JSON 对象。JqGrid 可以处理 XML 数据、JSON 数据以及数组,这里我们使用 JSON。正如我所提到的,我创建了一个名为 _JQGridHandler.ashx_ 的 .ashx 处理程序。并提供了处理程序的 URL 为 _https://:58404/JQGridHandler.ashx_。我将在这里向您展示如何通过简单地调用 URL 从处理程序读取从网格传递的数据。像往常一样,如果我们向处理程序传递任何数据并从处理程序中读取它,我们会查看哪个参数?是的,我们肯定会首先查看 `context.Request`,对吗?这里我们也将搜索 Form 参数中是否传递了任何数据。

让我们调试看看。

通过查看调试器和我设置的监视,您可以看到我正在通过调用 `forms.Get("oper");` 来寻找一个名为 `oper` 的东西,我希望您也注意到 `Form{}`(它是一个数组)属性在这里是空的。

那么我怎么才能得到 `oper` 呢?是的,所以网格数据操作取决于 `oper` 参数。接下来我会向你展示 `oper` 中可能出现的所有数据。所以这里我推断如果 `oper==null`,那就是网格第一次加载。不要混淆。

我会在几秒钟内让你明白。这里我使用 MONGO 数据库作为我的数据存储。

你可以在 if 语句中看到数据获取代码。我希望到目前为止一切都清楚。

无论如何,我不会深入研究处理程序、JSON、Mongo 等,您可以使用任何数据库。只有连接和数据获取机制会不同。

我之所以使用 mongo 是因为它非常简单易用。好的,现在我们已经完成了 JqGrid 的所有必要设置,让我们看看它是否有效。

数据会填充到网格中吗?

运行它...

嘿,它运行得很好...

来吧,我们去开派对。 微笑 | <img src= 你能相信表格 jQGridDemo 会这样吗?是的,就是这样,这就是 JqGrid...那么现在你可能会想,这个网格有什么特别之处...作为一个简单的网格视图而已...你注意到“名字”列标题上出现了可排序符号了吗?我们为它编写代码了吗?是的...

这就是网格的魅力所在。不仅是“名字”列,对于每一列,点击列标题,你都会在顶部列标题上看到排序按钮。

除非你添加一个如下所示的属性。

{name: 'Address', index: 'Address', width: 150, sortable: false}

(在此示例中,地址字段不可排序)这只是一个示例。

接下来您可以看到类似这样的现有功能。请系好安全带...

你准备好在 JqGrid 表格(`jQGridDemo`)底部再添加一个 div 了吗?我来给你展示魔术。去添加它...

<table id="jQGridDemo">
</table>
<div id="jQGridDemoPager">
</div>

是的,我在名为 `jQGridDemoPager` 的 div 底部添加了一个 div。脚本中的一些更改如下。

请注意突出显示的部分,它们是新添加的。

让我们看看我们的网格现在看起来怎么样。

带有刷新和搜索选项的分页栏出现了。

底部栏的优点是,对于搜索等操作,您甚至不需要编写一行代码。不仅是搜索,排序也一样。JqGrid 会为我们自动完成所有这些功能。

我们去尝试搜索。你注意到底部的搜索按钮了吗?搜索旁边还有一个刷新按钮。但是它的标签没有显示出来,对吗?

只是一个按钮而已。如果我们想给刷新按钮添加一个标签。只需打开 _grid.locale-en.js_ 文件并添加相应的文本即可。我将向你展示我是如何为该按钮添加标签的。

在该文件中有一个名为 `nav` 的部分,您可以在上面的图片中看到,其中有一个 `refreshtext`。最初它是空白的,添加您需要的文本。我在这里添加了“刷新”作为标签文本。

你注意到刷新按钮的标签现在变了吗?是的,它已经变了。还有另一种改变按钮标签的选项。

我之所以告诉你这种方法,是因为我想让你探索文件里面有什么。那么搜索弹出窗口呢?它很漂亮,对吧?而且我知道你也注意到了搜索条件,比如等于、不等于、开头是等等。你注意到了吗?

好的,请看上面的图片。你可以清楚地看到下拉列表中的搜索条件。有很多条件,无论如何,我不会在我们的 POC 中使用所有这些条件。我想删除所有这些不必要的条件。

如何做到?

如果你看过我之前提到的文件(_grid.locale-en.js_),你可能也在搜索部分看到了所有这些条件。

是的,搜索部分,他是唯一的罪魁祸首。让我们尝试删除它,看看会发生什么。

是的,我删除了那些不必要的搜索条件。如果您愿意,可以与上面的图片进行比较,同时检查搜索和排序是否如您预期那样进行。对我来说,它运行良好。

你们呢?:)我希望到这里为止几乎清楚了吧?我的下一个目的是让网格响应式。我们如何编辑网格?你认为这也可以不费吹灰之力完成吗?好吧,让我们看看。

JqGrid 编辑/添加/删除

在 JqGrid 中,所有事件和属性都是可配置的。这非常简单,但要小心。即使是很小的更改也可能使您的网格无法按预期工作。

要为您的网格提供上述功能,您必须按照我下面提到的确切顺序添加以下代码。

$('#jQGridDemo').jqGrid('navGrid', '#jQGridDemoPager',
{
   edit: true,
   add: true,
   del: true,
   search: true,
   searchtext: "Search",
   addtext: "Add",
   edittext: "Edit",
   deltext:"Delete"
},
{//EDIT EVENTS AND PROPERTIES GOES HERE },
{//ADD EVENTS AND PROPERTIES GOES HERE},
{//DELETE EVENTS AND PROPERTIES GOES HERE},
{//SEARCH EVENTS AND PROPERTIES GOES HERE}
);    

我提到事件和属性的顺序有一个口诀。

在第一个大括号里你添加了一些参数为 true。请看下面的图片,这是我从上面代码片段中实际解释的部分。

这意味着在网格导航栏(底部栏)中,所有提到的按钮都将显示为下面提到的相应文本。

为了更好地理解,我用相同的颜色标记了。这一部分你必须在 JqGrid 初始化事件和参数之后显式声明。

让我们来看看网格,看看发生了哪些变化。

请看突出显示的区域。您可以看到所有按钮都已显示,这些按钮是您在上面代码段中设置为 true 的。让我们添加一条记录。

点击底部导航栏上的小 + 添加符号。会弹出一个小窗口,如下图所示。

填写完并点击保存按钮。会发生什么?什么都不会发生:)。因为你没有为编辑操作配置任何东西。

要执行编辑/删除和添加操作,您还必须在网格中设置另一个 URL 属性,即 editurl。这将调用 .ashx 处理程序来执行添加操作。

您必须设置 editurl: 'https://:58404/JQGridHandler.ashx'。在 caption 下面。

您可以查看图像 7 来定位标题的位置。填写表格,然后点击保存。让我们看看会发生什么...

我在处理程序中设置了一个调试器,以检查保存是否到达处理程序。我知道你可能会想,来自 UI 的数据如何到达处理程序以插入到数据库中。

是的...正如预期,在点击保存按钮后,调试器在处理程序中被捕获。

你能看到表单中有什么吗(`context.Request.Form`)?是的,正是我们想要的。要插入的数据作为键值对。你注意到现在是 oper=add 了吗?

所以我希望您现在对 `oper` 有了比我之前在将数据加载到网格时解释时更多的了解。而且键值对的键将是在网格中指定的键,如 FirstName、LastName、Age 等。

希望你明白了。

因此,当 `oper` 的值为 add 时,add if 条件内的代码将执行以将记录添加到数据库。如何从表单中读取值?这非常简单。

string strFirstName = forms.Get("FirstName").ToString();

如上所示,您可以从 HTTP 请求的表单属性中读取任何值,将 FirstName 替换为您想要的内容。添加成功后,处理程序将向 HTTP 响应写入一个成功字符串。该字符串将显示在网格上方的添加/编辑弹出窗口中,如下所示。

您能看到顶部红色 Div 中显示的消息“员工记录添加成功”吗?

此响应是由处理程序发送的,是用户定义的。

您可能会想,在插入后,客户端的哪个事件会接收来自服务器端的响应,对吗?

******************************************************
Complete Script
******************************************************
$('#jQGridDemo').jqGrid('navGrid', '#jQGridDemoPager',
{
   edit: true,
   add: true,
   del: true,
   search: true,
   searchtext: "Search",
   addtext: "Add",
   edittext: "Edit",
   deltext:"Delete"
},
{   //EDIT portion
    //Can also set the width and height of the editing window as below commented way 
   //height: 300,
   //width: 400,
   //top: 50,
   //left: 100,
   //dataheight: 280,
   closeOnEscape: true,//Closes the popup on pressing escape key
   reloadAfterSubmit: true,
   drag: true,
   afterSubmit: function (response, postdata) {
       if (response.responseText == "") {
           $(this).jqGrid('setGridParam', 
             { datatype: 'json' }).trigger('reloadGrid');//Reloads the grid after edit
           return [true, '']
       }
       else {
           $(this).jqGrid('setGridParam', 
             { datatype: 'json' }).trigger('reloadGrid'); //Reloads the grid after edit
           return [false, response.responseText]
           //Captures and displays the response text on th Edit window
       }
   },
   editData: {
       EmpId: function () {
           var sel_id = $('#jQGridDemo').jqGrid('getGridParam', 'selrow');
           var value = $('#jQGridDemo').jqGrid('getCell', sel_id, '_id');
           return value;
       }
   }
},
{//ADD portion
   closeAfterAdd: true,//Closes the add window after add
   afterSubmit: function (response, postdata) {
       if (response.responseText == "") {
           $(this).jqGrid('setGridParam', 
             { datatype: 'json' }).trigger('reloadGrid')//Reloads the grid after Add
           return [true, '']
       }
       else {
           $(this).jqGrid('setGridParam', 
             { datatype: 'json' }).trigger('reloadGrid')//Reloads the grid after Add
           return [false, response.responseText]
       }
   }
},
{   //DELETE
   closeOnEscape: true,
   closeAfterDelete: true,
   reloadAfterSubmit: true,
   closeOnEscape: true,
   drag: true,
   afterSubmit: function (response, postdata) {
       if (response.responseText == "") {
           $("#jQGridDemo").trigger("reloadGrid", [{ current: true}]);
           return [false, response.responseText]
       }
       else {
           $(this).jqGrid('setGridParam', { datatype: 'json' }).trigger('reloadGrid')
           return [true, response.responseText]
       }
   },
   delData: {
       EmpId: function () {
           var sel_id = $('#jQGridDemo').jqGrid('getGridParam', 'selrow');
           var value = $('#jQGridDemo').jqGrid('getCell', sel_id, '_id');
           return value;
       }
   }
},
{//SEARCH
   closeOnEscape: true
}
);

上面的代码本身就是自解释的。我已经在上面的代码片段中包含了编辑和删除的代码。

我想说的一件重要的事情是关于编辑。在执行编辑操作时,我们总是根据某个主键更新数据,对吧?这里的主键是 _id。(_id 是 employeeid)

在编辑或更新时,只有标记为可编辑的字段的数据才会传输到处理程序。不会传输任何额外数据。

如果你查看编辑窗口,其中 _id 没有显示或标记为可编辑(默认情况下,所有字段都是可编辑的,除非添加编辑参数),因此它不会在 `context.request.Form` 中传输到处理程序。

为了将该 _id(即 employeeid)从我们的 JqGrid 传递到服务器,我使用了 JqGrid 的 `editData` 属性。我们可以使用 JqGrid 的 `delData` 属性来传递 _id 以删除记录。

注意:不仅仅是 _id,您还可以借助 JSON 格式的 `editData,delData` 将任何额外数据传递给处理程序。

您可以在上面的 JS 代码中看到这一点。我必须提到的另一个重要提示是从 JqGrid 的特定单元格中获取数据。

var sel_id = $('#jQGridDemo').jqGrid('getGridParam', 'selrow');
//Gets the Id of selected row

var value = $('#jQGridDemo').jqGrid('getCell', sel_id, '_id');
//Gets the value of column of selectedrow.(_id is the na,e of the column). 
*******************************************************
Code in HTTP  handler
*******************************************************
public class JQGridHandler : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        System.Collections.Specialized.NameValueCollection forms = context.Request.Form;
        string strOperation = forms.Get("oper");
        MONGOConnect objMC = new MONGOConnect();//Helper Class
        var collectionEmployee = 
          objMC.GetMongoCollection("EMPLOYEE");//Gets Employee Collection
        string strResponse = string.Empty;
        if (strOperation == null)
        {
            //oper = null which means its first load.
            var jsonSerializer = new JavaScriptSerializer();
            context.Response.Write(jsonSerializer.Serialize(
              collectionEmployee.AsQueryable<Employee>().ToList<Employee>()));
        }
        else if (strOperation == "del")
        {
            var query = Query.EQ("_id", forms.Get("EmpId").ToString());
            collectionEmployee.Remove(query);
            strResponse = "Employee record successfully removed";
            context.Response.Write(strResponse);
        }
        else
        {
             string strOut=string.Empty;
             AddEdit(forms, collectionEmployee, out strOut);
             context.Response.Write(strOut);
        }
                   
    }
    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
    private void AddEdit(NameValueCollection forms, 
      MongoCollection collectionEmployee,out string strResponse)
    {
        string strOperation = forms.Get("oper");
        string strEmpId = string.Empty;
        if (strOperation == "add")
        {
             strEmpId = forms.Get("EmpId").ToString();
        }
        else if (strOperation == "edit")
        {
            var result = collectionEmployee.AsQueryable<Employee>().Select(c => c._id).Max();
             strEmpId = (Convert.ToInt32(result) + 1).ToString();
        }
       
        string strFirstName = forms.Get("FirstName").ToString();
        string strLastName = forms.Get("LastName").ToString();
        string strLastSSN = forms.Get("LastSSN").ToString();
        string strDepartment = forms.Get("Department").ToString();
        string strAge = forms.Get("Age").ToString();
        string strSalary = forms.Get("Salary").ToString();
        string strAddress = forms.Get("Address").ToString();
        string strMaritalStatus = forms.Get("MaritalStatus").ToString();
        Employee objEmp = new Employee();
        objEmp._id = strEmpId;
        objEmp.FirstName = strFirstName;
        objEmp.LastName = strLastName;
        objEmp.LastSSN = strLastSSN;
        objEmp.Department = strDepartment;
        objEmp.Age = Convert.ToInt32(strAge);
        objEmp.Address = strAddress;
        objEmp.MaritalStatus = strMaritalStatus;
        objEmp.Salary = strSalary;
        collectionEmployee.Save(objEmp);
        strResponse = "Employee record successfully updated";
    }
}

根据 `strOperation(forms.Get("oper"))` 中的值,null、add、edit 和 del 将执行处理程序中的操作并发回自定义响应。仅此而已。

您可以看到删除操作是什么样子。

第二部分JqGrid 行内编辑
第三部分: JqGrid 与 MVC

 

结论

JqGrid 是一个非常时尚且易于集成的网格,拥有许多令人惊叹的功能。

如果有人要求您在短时间内构建一个具有所有这些搜索、排序、过滤选项的应用程序,您可以非常放心地选择 JqGrid。

另外,我建议在快速应用程序开发中使用 MongoDB 会非常有用。对于这个演示应用程序,我使用 MongoDB 作为后端数据库,因此我能够很快完成。

如果您使用我们的网格视图和 SQL Server 进行开发,开发一个具有所有这些功能的应用程序需要多少小时?使用 JqGrid 开发所需时间要少得多,如果使用 MongoDB 则更少。我不是在推广 MongoDB,但这只是我根据经验写下来的。JqGrid 还有许多其他功能有待探索,这就是为什么我在介绍中提到它只是冰山一角。

© . All rights reserved.