文章提綱
-
介紹 & 使用場景
-
JqGrid的一些說明
-
JqGrid和ASP.NET整合詳細步驟
前置准備
框架搭建
數據填充
數據增/刪/改
其他
介紹&使用場景
JqGrid不是一個新鮮玩意,已經是一個久經證明的開源數據顯示控件了。
園子里也有一些介紹文章,為什么還要寫這篇文章呢?
因為還找不到可以完整講述JqGrid集成的文章,我指的是從頭至尾的完整的講述,而不是其中一些片段或介紹一些參數。
正好在看到一篇文章完整的講述了這個步驟: http://www.codeproject.com/Articles/609442/Using-JqGrid-in-ASP-NET
本文主要參考了這篇文章,講述jqGrid和ASP.NET集成。
使用場景:
數據多且雜時,如果想要給表格數據的顯示增加方便的查詢/刪選功能。
JqGrid免費,開源,使用方便,是一個不錯的選擇。
JqGrid的一些說明
- 外觀時髦,功能齊全
- JS控件,用來顯示和操作表格數據
- 使用AJAX方式
- 可以被集成到任何服務器端技術,例如ASP, JavaServelets, JSP, PHP 等等.
- 由Trirand公司Tony Tomov開發.
- 和ASP.NET集成非常簡單
JqGrid和ASP.NET整合詳細步驟
- 下載JqGrid,添加所需的文件到ASP.NET應用程序 (主要是一些Scripts and CSS).
- 在需要使用的頁面中初始化JqGrid.
- 綁定數據
- 其他一些操作,如增刪改
1. 我提到的第一點,你可以在以下地址下載JqGrid和相關的文件
http://www.trirand.com/blog/?page_id=6
下載得到jquery.jqGrid-4.5.2.zip.
將文件解壓,里面是一些css和script文件夾, 讓我們去看看如何去使用這些文件。
為了更好的理解, 按照國際慣例我新建了一個demo程序:JQGridPOC,用來展示集成的步驟和所具有的功能。
我們需要引入的主要文件是jQuery, 因為jqGrid依賴於jQuery .
在解決方案中專門新建一個文件夾JQGridReq用來放JqGrid相關的文件。
第一步,添加jQuery文件(我添加了jQuery 1.9)。
第二步,如果我們要如何使用jQuery中任何UI相關的東西? 是的,CSS文件. 去jQuery的官網下載。
最后一步,添加Jquery-ui-1.9.2.custom.css 到程序中。
請確保你同時添加了相關的圖片文件夾,因為我們添加的CSS可能也會用到相關的圖片。
這樣jQuery的東西就准備好了。
下面再開始逐個添加我們JqGrid文件。
- jquery.jqGrid-4.5.2\src\ jquery.jqGrid.js
- jquery.jqGrid-4.5.2\js\i18n\ grid.locale-en.js
- jquery.jqGrid-4.5.2\js\i18n\ grid.locale-cn.js
- jquery.jqGrid-4.5.2\css\ ui.jqgrid.css
你看到上面添加的locale-en.js/local-en.js文件了嗎? 他們非常重要,可以在里面更改一些預設的參數。
同樣的,我們也添加了CSS文件.
現在我們先決條件都完成了。
如下圖,你可以看到我們添加后的文件和文件夾結構.
讓我們去.aspx 頁面添加JqGrid吧。
這個簡單的示例項目中我使用了簡單的客戶管理的案例,使用Default.aspx 做為例子。
需要將所有需要的文件先引用到HTML頁的head部分,如下圖。
現在需要做的是先將HTML table標簽放置到頁面中,給這個table指定一個ID jQgridPOC (這個table就是我們即將要轉變成的JqGrid)。
2. 在需要使用的頁面中初始化JqGrid.
下面將要將這個table轉變成JqGrid.
准備好我們將要打算顯示在Grid中的字段,我們初始化table的時候必須帶上這些字段。
我們准備顯示的是:
- UniqueID
- First Name
- Last Name
- City
- State
- Address.
你可以使用下面腳本將HTML table初始化成grid.
代碼片段:
</script>
運行程序,你將會得到下圖所示表格(目前還沒數據)。
我想根據表格顯示內容,你應該能讀懂我寫的初始化腳本。
colNames代表表格頭部.
colModel是JSON對象數據的屬性,用來配置表格中的每一列。
可以說要在表格中顯示的數據模型。colNames中的屬性順序應該和colModel中數組的順序相匹配。
你也許注意到url屬性留着沒有填。
那是供AJAX調用的,下面就完成這部分內容,填充這個grid.
我使用SQL Server的示例數據庫PETSHOP作為后端.
URL如何完成填充數據?
我所做的是, 創建一個HTTP handler, handler里面的函數去取表 [MSPetShop4Profile].[dbo].[Account] 中的數據並且寫到HTTP Response中去。
HTTP response將會是一個JSON字符串,按照之前提到的colModel的格式。
我們的JqGrid讀取JSON返回字符串,在colModel的幫助下顯示在JqGrid里。
你需要留意一下,目前我們使用JSON對象。
JqGrid可以使用XML,JSON,數組,我們使用的是JSON。
正如我所說的,我創建了一個.ashx handler,叫JQGridHandler.ashx
相應的url地址為:http://localhost:58404/JQGridHandler.ashx.
下面就向你展示數據如何從handler中讀取。從grid中訪問handler僅僅只需要調用URL
通常,如果我們需要傳遞數據到handler或從handler中讀取數據,我們在哪找傳遞的參數?
是的,我們顯然會首先去context.Request中找,不是嗎?
此時我們也會去看看在 context request 中是否有表單參數數據傳遞進來。
讓我們去調試看看。
通過查看調試器(如上圖),你可以看到我在通過調用forms.Get(“oper”) 找 oper 的值。
希望你已經注意到了 Form{}
屬性是空的。
那么為什么我會取oper的值呢?
我想你已經猜到了,grid操作數據時會依賴oper 參數。
繼續往下看,我將會向你展示oper中的所有數據。
現在我們假設 oper==null
時代表grid是第一次加載。不要感到困惑。
下面我使用SQL Server數據庫作為我的數據存儲。
關於ADO.NET這塊我不做討論,主要用了一個類文件SQLHelper和兩個函數
private DataTable GetAccountInfo()
public string GetJson(DataTable dt)
可自行在代碼中查看。
另外需要說明的是我取回的數據源是DataTable,需要轉換成JSON,用了public string GetJson(DataTable dt)進行轉換。
你也可以使用其他數據源,用你熟悉的就好。
你可以看到取數據的代碼在if語句中。
我希望到現在為止一切都說的很清楚。
現在好了,我們為JqGrid鋪好了數據管道,讓我們看看是否可以工作。
數據會被裝載進來嗎?
CTRL+F5
數據已經被裝載進來了。
現在可以在這個基礎上做一些變化了。
你也許會想這個表格有什么特別呢?和一個簡單的gridview一樣。。。
你點一下第二列的表頭"大名"試試,直接就能排序了。
我們給排序寫代碼了嗎?
沒錯,這就是jqGrid的優雅之處。不光是第一列,每一列的表頭都可以進行排序。
除非你加了如下sortable : false屬性,如下:
{ name: 'State', index: 'State', width: 80, sortable: false, editable: true }
(這里State這個字段是不能排序的)
繼續向下,你能看到其他一些激動人心的功能 :)
在JqGrid table (jQGridPOC
)下面再添加一個div. 如下
<table id="jQGridPOC"></table><div id="jQGridPOCPager"></div>
是的,我在底部又添加了一個div jQGridPOCPager.
腳本做一些修改,如下
注意方框部分是我新增加的。
看看現在Grid是什么樣了.
頁碼工具欄出現了。
這個底部工具欄的優雅之處在於,不用寫一行代碼就能完成搜索功能。
不光是搜索,排序功能也能同樣不需要寫代碼就能實現,JqGrid原生就能實現這些功能。
下面對這個工具欄做一些設置相關配置如下(如圖9,10)。
讓我們試一下查找功能. (如圖11)
說明一下,你可以在grid.locale-cn.js-->nav 片段中修改底部工具欄中的一些default設置(顯示文字,跳出模態框的標題等),如圖12.
當然 ,你可以在JqGrid初始化時修改這些默認設定,如圖13。
另外你應該注意到了圖11中的篩選條件例如等於,不等,開始於等等。
我不需要用這么多的篩選條件,怎樣移除?
如果已經把grid.locale-cn.js都瀏覽一遍,你應該已經發現這些條件在grid.locale-cn.js-->search片段中。
是的,只要修改這些就可以了,你可以移除一些試試看。(如下圖方框處)
這個文件中的其他片段的作用相信你能根據代碼猜測出來,自己去探索一下吧 :)
希望到此處你都能理解。
下一步打算給grid添加數據庫交互功能,即增刪改功能。
讓我們一起來看看吧。
4.JqGrid Edit/Add/Delete
JqGrid所有的事件和屬性都是可配置的,用起來很簡單。
不過要注意,即使是一點小改動也可能讓grid不能按你期望的工作.
為了完成我們的增刪改功能,搭建下面代碼的框架。注意按照我下面示例的順序。

$('#jQgridPOC').jqGrid('navGrid', '#jQGridPOCPager', { edit: true, add: true, del: true, search: true, searchtext: "查找", addtext: "添加", edittext: "編輯", deltext: "刪除", refreshtext:"刷新" }, { //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, 添加了按鈕后面的文字說明。這個部分我上面已經提到過了。
這代表在grid的底部導航欄中,所有的button將會顯示,並且分別顯示相對應的文字。(如下圖15)
僅接着的幾個大刮號是對應的JqGrid的初始化事件和參數。
讓我們看一下grid,上面的改動都生效了。
請注意上圖的方框部分。我們點擊 “添加” 來增加一筆資料。
將會跳出一個小窗(如下面的截圖)
填寫后點提交會提示 沒有設置url 錯誤。因為我們還沒完成這部分功能呢。
要想執行增刪改操作,你需要在grid中添加一個URL屬性即editurl.
這個url將會去調用.ashx handler去執行添加功能。
保存修改,在handler入口處加個斷點,調試。
重復上面添加提交步驟,看到 context.Request.Form 中的值了嗎,完全和我們預期的一樣。
我們要的數據已經都可以獲得了,可以看到forms.Get("oper")已經可以得到值 "add" 了。
根據上面調試的截圖你應該可以對我們之前提到的 oper
有更多的了解,前面是在加載數據到grid中提到的。
鍵值對中鍵對應grid中的字段,例如FirstName, LastName等。
理解了嗎?
示例代碼中我將增加和編輯都放在了同一個分支中,根據相應的if分支就可以執行插入數據到DB的功能了。
string strFirstName = forms.Get("FirstName").ToString();
如上面的寫法,同樣方法你可以從HTTP request讀取表單中其他值.
插入成功后handler將會寫一筆插入成功的字符串到HTTP response中.
這個字符串將會顯示在彈出框中,如下圖“資料添加成功”。
這個返回的信息是從handler中發送的,從示例代碼中應該很容易找到。
你也許會想客戶端哪些事件會接收server端的response, 完整的腳本如下,我將編輯和刪除也加上了。

$(function () { $("#jQgridPOC").jqGrid({ url: 'http://localhost:58404/JQGridHandler.ashx', datatype: "json", colNames: ['Id', '大名', '尊姓', "地址", '城市', '州','國家'], colModel: [ { name: 'id', index: 'id', width: 20, stype: 'text' }, { name: 'FirstName', index: 'FirstName', width: 80, stype: 'text', sortable: true, editable: true }, { name: 'LastName', index: 'LastName', width: 80, align: "right", editable: true }, { name: 'Address1', index: 'Address1', width: 150, align: "right", editable: true }, { name: 'City', index: 'City', width: 100, align: "right", editable: true }, { name: 'State', index: 'State', width: 80, sortable: false, editable: true }, { name: 'Country', index: 'Country', width: 80, sortable: false, editable: true } ], rowNum: 10, loadonce: true, rowList: [10, 20, 30], pager: '#jQGridPOCPager', sortname: 'LastName', viewrecords: true, sortorder: 'desc', caption: "客戶列表", editurl: 'http://localhost:58404/JQGridHandler.ashx' }); $('#jQgridPOC').jqGrid('navGrid', '#jQGridPOCPager', { edit: true, add: true, del: true, search: true, searchtext: "查找", addtext: "添加", edittext: "編輯", deltext: "刪除", refreshtext:"刷新" }, { //EDIT // 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; } } }, { 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, 即我們數據庫中的 UniqueID.
特別需要說明的是,編輯更新時,只有標記為editable才能傳遞到handler中去。
如果把字段editable標記為false或不標記,就不會在跳出的編輯框中顯示。
你可以看一下編輯時_id沒顯示,因為這個字段沒有標記為editable因此就不會傳遞到handler中去。
說明:原來用的示例數據庫中Account表,不過發現有一些主外鍵約束及多余字段不方便演示,我又新建了個類似的表AccountTEST(刪除了一些多余字段)。
為了把_id值從我們的grid中傳遞到server中,我使用了JqGrid中的editData 屬性。
同樣我們也可以利用delData屬性傳遞 _id去刪除數據。
注意:不光是_id,你可以傳遞任何數據到handler中去,使用JSON格式的editData,delData
從上面的代碼可以看出,另外一個常用技巧是獲取選中行的數據。
通過下面兩行代碼:先獲取選中行,再選取該行中所要的字段。
根據strOperation(forms.Get("oper"))
null, add, edit, del執行不同的操作。最后handler的代碼也做個總結

public class JQGridHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { NameValueCollection forms = context.Request.Form; string strOperation = forms.Get("oper"); string strResponse = string.Empty; if (strOperation == null) //oper = null which means its first load. { //1.get the sample data DataTable dt = GetAccountInfo(); //2.convert to json string jsonRes = GetJson(dt); context.Response.Write(jsonRes); } else if (strOperation == "del") { string strEmpId = forms.Get("id").ToString(); DeleteEmployee(strEmpId); strResponse = "刪除成功"; context.Response.Write(strResponse); } else { string strOut = string.Empty; AddEdit(forms, out strOut); context.Response.Write(strOut); } } public bool IsReusable { get { return false; } } private DataTable GetAccountInfo() { DataTable dt = null; string cmdText = @"SELECT [UniqueID] id ,[FirstName] ,[LastName] ,[Address1] ,[City] ,[State] ,[Country] FROM [MSPetShop4Profile].[dbo].[AccountTest]"; SQLHelper sqlhelper = new SQLHelper(); dt = sqlhelper.ExecuteQuery(cmdText, CommandType.Text); return dt; } //convert a data table to JSON format public string GetJson(DataTable dt) { JavaScriptSerializer serializer = new JavaScriptSerializer(); List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>(); Dictionary<string, object> row = null; foreach (DataRow dr in dt.Rows) { row = new Dictionary<string, object>(); foreach (DataColumn col in dt.Columns) { row.Add(col.ColumnName.Trim(), dr[col]); } rows.Add(row); } return serializer.Serialize(rows); } private void AddEdit(NameValueCollection forms, out string strResponse) { string strOperation = forms.Get("oper"); string strEmpId = string.Empty; string strFirstName = forms.Get("FirstName").ToString(); string strLastName = forms.Get("LastName").ToString(); string strAddress = forms.Get("Address1").ToString(); string strCity = forms.Get("City").ToString(); string strState = forms.Get("State").ToString(); string strCountry = forms.Get("Country").ToString(); Employee objEmp = new Employee(); objEmp._id = strEmpId; objEmp.FirstName = strFirstName; objEmp.LastName = strLastName; objEmp.Address1 = strAddress; objEmp.City = strCity; objEmp.State = strState; objEmp.Country = strState; if (strOperation == "add") { InsertEmployee(objEmp); strResponse = "資料添加成功"; return; } else if (strOperation == "edit") { strEmpId = forms.Get("id").ToString(); objEmp._id = strEmpId; UpdateEmployee(objEmp); strResponse = "資料更新成功"; } strResponse = "更新有問題,請聯系管理員"; } //insert public bool InsertEmployee(Employee employee) { bool flag = false; SQLHelper sqlhelper = new SQLHelper(); string cmdText = @"INSERT INTO [MSPetShop4Profile].[dbo].[AccountTest] ([FirstName] ,[LastName] ,[Address1] ,[City] ,[State] ,[Country]) VALUES (@FirstName ,@LastName ,@Address1 ,@City ,@State ,@Country)"; SqlParameter[] paras = new SqlParameter[]{ new SqlParameter("@FirstName",employee.FirstName), new SqlParameter("@LastName",employee.LastName), new SqlParameter("@Address1",employee.Address1), new SqlParameter("@City",employee.City), new SqlParameter("@State",employee.State), new SqlParameter("@Country",employee.Country) }; try { int res = sqlhelper.ExecuteNonQuery(cmdText, paras, CommandType.Text); if (res > 0) { flag = true; } } catch (Exception ex) { throw ex; } return flag; } //update public bool UpdateEmployee(Employee employee) { bool flag = false; SQLHelper sqlhelper = new SQLHelper(); string sql = @"UPDATE [MSPetShop4Profile].[dbo].[AccountTEST] SET [FirstName] = @FirstName ,[LastName] = @LastName ,[Address1] = @Address1 ,[City] = @City ,[State] = @State ,[Country] = @Country WHERE UniqueID=@UniqueID"; SqlParameter[] paras = new SqlParameter[]{ new SqlParameter("@UniqueID",employee._id), new SqlParameter("@FirstName",employee.FirstName), new SqlParameter("@LastName",employee.LastName), new SqlParameter("@Address1",employee.Address1), new SqlParameter("@City",employee.City), new SqlParameter("@State",employee.State), new SqlParameter("@Country",employee.Country) }; int res = sqlhelper.ExecuteNonQuery(sql, paras, CommandType.Text); if (res > 0) { flag = true; } return flag; } //delete public bool DeleteEmployee(string id) { bool flag = false; SQLHelper sqlhelper = new SQLHelper(); string sql = @"DELETE FROM [MSPetShop4Profile].[dbo].[AccountTEST] WHERE UniqueID=@UniqueID"; SqlParameter[] paras = new SqlParameter[]{ new SqlParameter("@UniqueID",id) }; int res = sqlhelper.ExecuteNonQuery(sql, paras, CommandType.Text); if (res > 0) { flag = true; } return flag; } }
OK, done.
總結
JqGrid優雅,功能豐富易集成,對表格數據進行操作。
JqGrid還有很多功能,各位看官自行探索吧。
參考文章的作者使用了MONGO這個open-source document database,有興趣的可以去研究下。
第一次寫長文章,如果有幫助,請猛戳推薦 :)
更新:
源碼地址:http://yunpan.cn/QD96IGcIbZyNG