在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
数据显示的方式可以通过很多控件来实现,例如服务端的原生GridView,第三方控件ComponentArt、Telerik等,客户端的flexgrid, extgrid, easyui, jqgrid等等。在这里我要讲解的是jqgrid,它也是我最近在项目中尝试用到的。 我选择使用jqgrid主要是因为它基于jquery ui,在没有美工、契合系统主题并且快速完成系统的前提下,我选择了可以定制theme的jquery ui. 这篇文章主要涉及到jquery ui和jqgrid的使用,我对每一步的讲解都尽量做到细化,结合详细的截图,以期能够通过step by step让初学者们熟悉一些原理和实现步骤。 文中涉及到一些其他知识点,也做了较为详细的说明,希望这些内容能够对web开发者们有较好的增益作用。 每一个页面的在线demo我还在配置中,一会儿放出来,可以让大家有个直观的感受。 本章概要:
在开始项目之前,需要做的一些准备我也会逐步在下面的内容中进行介绍,或者你可以直接在这里下载本文所有demo的源代码,源代码中已经为你准备好这些文件,并且这些都是可以运行的。 源代码下载:KFBlogDemo.zip 一、 Json标准格式和验证由于自己在使用jqgrid的过程中曾经使用过不规范的json,导致数据jqgrid一直无法显示,所以在此有必要简单讲一下json的标准格式和验证方式。 虽然在js中字符串也可以用单引号来表示,但是json的标准格式是用双引号把属性和值给括起来的,注意是属性和值(当然数值类型的值可以省去双引号)。下列Json格式中除了最后一条是标准的,前面几条都是不标准的。
{ 'name' : 'keepfool' } // 错误格式,proerty和value应用双引号 { name: 'keepfool' } // 错误格式,property应用双引号括起来,value应用双引号 { name: "keepfool" } // 错误格式,property应用双引号括起来 { "name" : 'keepfool' } // 错误格式,value应用双引号 { "name" : "keepfool" } // 标准格式 有时候手动生成json格式的字符串,可能会不符合标准,可以通过下面两个在线验证工具执行验证,我推荐使用第一个,因为它能够准确的定位出json串出错的地方,下面的几个例子也是通过第一个在线工具做验证的。 例子1(属性没带引号): { id: "1", "invdate": "2010-05-24", "name": "test", "note": "note", "tax": "10.00", "total": "2111.00" } 例子2(属性带单引号): { "id": "1", "invdate": '2010-05-24', "name": "test", "note": "note", "tax": "10.00", "total": "2111.00" } 例子3(正确): { "id": "1", "invdate": "2010-05-24", "name": "test", "note": "note", "tax": "10.00", "total": "2111.00" } 二、jquery ui theme的使用在文章的开篇我已经提到过jquery ui,它的使用方式我会在下面一步一步列出来,希望对那些还不太会使用jquery ui theme的童鞋们有所帮助。 1. 项目创建在VS下创建一个Web网站或者Web应用程序,创建一个themes目录。如下图: 2. Base Theme的使用先到http://jqueryui.com/themeroller/下载一个theme,就选那个最基本的灰色调的。
然后会看到下面这个画面,甭管左边有哪些组件,直接download. 把下载得到的jquery-ui-1.8.16.custom.zip文件解压出来,找到base目录(\jquery-ui-1.8.16.custom\development-bundle\themes\base),将base目录复制到themes文件夹下。 找到ui目录(\jquery-ui-1.8.16.custom\development-bundle\ui\),同样将其复制到themes目录下,ui目录包含三部分:
现在基本的准备都已经做好了,下面我们来创建第一个页面BaseTheme.html,并演示一个手风琴的效果(accordion组件),请看基础并且关键的步骤: (1). 引用jquery ui css <link rel="Stylesheet" type="text/css" href="themes/base/jquery.ui.all.css" /> (2). 引用jquery ui js <script type="text/javascript" src="themes/ui/jquery.ui.core.js"></script> <script type="text/javascript" src="themes/ui/jquery.ui.widget.js"></script> <script type="text/javascript" src="themes/ui/jquery.ui.accordion.js"></script> (3). 手风琴html代码 <div class="demo"> <h1> Base Demo</h1> <div id="accordion"> <h3><a href="#">Section 1</a></h3> <div> <p>A.</p> </div> <h3><a href="#">Section 2</a></h3> <div> <p> B. </p> </div> </div> </div> (4). 实现jquery 手风琴效果 <script type="text/javascript"> $(function() { $("#accordion").accordion({ collapsible: true }); }); </script> 最终的效果如下图,当然完整的代码已经包含在下载文件中了,您也可以直接运行里面的代码。 3. theme的使用方式Base Theme的使用方式我们已经使用过了,但是这个灰色调的主题可能并不符合您网站的主题色调,不过幸运的是http://jqueryui.com/themeroller/已经为我们提供了很多种不同色调而且比较美观的主题,你可以自行去下载。当然如果你觉得某一款主题看起来不错,但某些样式还需要一些轻微的改动才能应用到自己的程序中,你可以使用Edit去进行编辑,然后生成自己需要的主题。 在第2步中已经列出了jquery ui的使用方式,如果你想换一个主题使用,方式和上面的代码步骤是相同的。
唯一不同之处是对css的引用 <link rel="Stylesheet" type="text/css" href="themes/theme_lightness/jquery.ui.all.css"/> 这里演示的例子都是accordion的,如果你想尝试其他的jquery ui组件,可以自行更换。但关键的两行代码是必不可少的,它们是jquery ui组件的基础: <script type="text/javascript" src="themes/ui/jquery.ui.core.js"></script> <script type="text/javascript" src="themes/ui/jquery.ui.widget.js"></script> 4. 主题切换的实现有了前面的基础,要实现主题切换已经很简单了,因为我们已经知道jquery theme的关键之处——引用jquery.ui.all.css,请看代码: 步骤I <link rel="Stylesheet" type="text/css" href="themes/theme_lightness/jquery.ui.all.css" id="theme" > 步骤II <div> 请选择主题: <select id="theme_changer"> <option value="themes/base/jquery.ui.all.css">Base Theme</option> <option value="themes/theme_lightness/jquery.ui.all.css" selected="selected">Lightness Theme</option> </select> </div> 步骤III <script type="text/javascript"> $(document).ready(function() { $('#theme_changer').change(function() { var theme = $(this).find("option:selected").val(); $('#theme').attr('href', theme); }); }); </script> 效果图: 5. 单个页面多主题的实现单个页面多主题的实现需要在http://jqueryui.com/download页面下载时多做一个步骤——指定css scope
点击CSS Scope后面的 按钮,你会发现css scope是专门针对多主题应用。 下面是完整的代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>多主题</title> <link rel="shortcut icon" href="/images/favicon.ico" /> <!--应用base主题和lightness主题--> <link rel="Stylesheet" type="text/css" href="themes/base/jquery.ui.all.css" /> <link rel="Stylesheet" type="text/css" href="themes/theme_lightness/jquery.ui.all.css" /> <link rel="Stylesheet" type="text/css" href="themes/demos.css" /> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> <script type="text/javascript" src="themes/ui/jquery.ui.core.js"></script> <script type="text/javascript" src="themes/ui/jquery.ui.widget.js"></script> <script type="text/javascript" src="themes/ui/jquery.ui.accordion.js"></script> <script type="text/javascript"> $(function() { $(".accordion").accordion({ collapsible: true }); }); </script> </head> <body> <div class="demo"> <h1> Base Demo</h1> <div class="accordion"> <h3> <a href="#">Section 1</a></h3> <div> <p> A.</p> </div> <h3> <a href="#">Section 2</a></h3> <div> <p> B. </p> </div> </div> <div class="space"> </div> <h1> Lightness Demo</h1> <!--主题中如果包含css scope,需要指定css scope,才能让主题生效--> <div class="lightness"> <div class="accordion"> <h3> <a href="#">Section 1</a></h3> <div> <p> A.</p> </div> <h3> <a href="#">Section 2</a></h3> <div> <p> B. </p> </div> </div> </div> </div> </body> </html> 效果如下: 三、jqgrid的使用方式上面的两大步都是为了使用jqgrid做准备,冗长的叙述和截图看起来很多,其实知道是jquery ui是怎么回事儿以后就会觉得很简单,步骤也不多。 jqgrid的项目地址:http://www.trirand.com/blog/,目前最新的版本是4.3的,也是我正在使用的版本。 1. jqgrid的local data使用方式请看代码示例1: <script type="text/javascript"> var mydata = [ { id: "1", invdate: "2010-05-24", name: "test", note: "note", tax: "10.00", total: "2111.00" }, { id: "2", invdate: "2010-05-25", name: "test2", note: "note2", tax: "20.00", total: "320.00" }, { id: "3", invdate: "2007-09-01", name: "test3", note: "note3", tax: "30.00", total: "430.00" }, { id: "4", invdate: "2007-10-04", name: "test", note: "note", tax: "10.00", total: "210.00" }, { id: "5", invdate: "2007-10-05", name: "test2", note: "note2", tax: "20.00", total: "320.00" }, { id: "6", invdate: "2007-09-06", name: "test3", note: "note3", tax: "30.00", total: "430.00" }, { id: "7", invdate: "2007-10-04", name: "test", note: "note", tax: "10.00", total: "210.00" }, { id: "8", invdate: "2007-10-03", name: "test2", note: "note2", amount: "300.00", tax: "21.00", total: "320.00" }, { id: "9", invdate: "2007-09-01", name: "test3", note: "note3", amount: "400.00", tax: "30.00", total: "430.00" }, { id: "11", invdate: "2007-10-01", name: "test", note: "note", amount: "200.00", tax: "10.00", total: "210.00" }, { id: "12", invdate: "2007-10-02", name: "test2", note: "note2", amount: "300.00", tax: "20.00", total: "320.00" }, { id: "13", invdate: "2007-09-01", name: "test3", note: "note3", amount: "400.00", tax: "30.00", total: "430.00" }, { id: "14", invdate: "2007-10-04", name: "test", note: "note", amount: "200.00", tax: "10.00", total: "210.00" }, { id: "15", invdate: "2007-10-05", name: "test2", note: "note2", amount: "300.00", tax: "20.00", total: "320.00" }, { id: "16", invdate: "2007-09-06", name: "test3", note: "note3", amount: "400.00", tax: "30.00", total: "430.00" }, { id: "17", invdate: "2007-10-04", name: "test", note: "note", amount: "200.00", tax: "10.00", total: "210.00" }, { id: "18", invdate: "2007-10-03", name: "test2", note: "note2", amount: "300.00", tax: "20.00", total: "320.00" }, { id: "19", invdate: "2007-09-01", name: "test3", note: "note3", amount: "400.00", tax: "30.00", total: "430.00" }, { id: "21", invdate: "2007-10-01", name: "test", note: "note", amount: "200.00", tax: "10.00", total: "210.00" }, { id: "22", invdate: "2007-10-02", name: "test2", note: "note2", amount: "300.00", tax: "20.00", total: "320.00" }, { id: "23", invdate: "2007-09-01", name: "test3", note: "note3", amount: "400.00", tax: "30.00", total: "430.00" }, { id: "24", invdate: "2007-10-04", name: "test", note: "note", amount: "200.00", tax: "10.00", total: "210.00" }, { id: "25", invdate: "2007-10-05", name: "test2", note: "note2", amount: "300.00", tax: "20.00", total: "320.00" }, { id: "26", invdate: "2007-09-06", name: "test3", note: "note3", amount: "400.00", tax: "30.00", total: "430.00" }, { id: "27", invdate: "2007-10-04", name: "test", note: "note", amount: "200.00", tax: "10.00", total: "210.00" }, { id: "28", invdate: "2007-10-03", name: "test2", note: "note2", amount: "300.00", tax: "20.00", total: "320.00" }, { id: "29", invdate: "2007-09-01", name: "test3", note: "note3", amount: "400.00", tax: "30.00", total: "430.00"}]; $(document).ready(function() { $("#gridTable").jqGrid({ data: mydata, datatype: "local", height: 150, rowNum: 10, rowList: [10, 20, 30], colNames: ['Inv No', 'Date', 'Client', 'Amount', 'Tax', 'Total', 'Notes'], colModel: [ { name: 'id', index: 'id', width: 60, sorttype: "int" }, { name: 'invdate', index: 'invdate', width: 90, sorttype: "date", formatter: "date" }, { name: 'name', index: 'name', width: 100 }, { name: 'amount', index: 'amount', width: 80, align: "right", sorttype: "float", formatter: "number" }, { name: 'tax', index: 'tax', width: 80, align: "right", sorttype: "float" }, { name: 'total', index: 'total', width: 80, align: "right", sorttype: "float" }, { name: 'note', index: 'note', width: 150, sortable: false } ], sortname: 'id', sortorder: 'desc', pager: "#gridPager", viewrecords: true, caption: "Manipulating Array Data" }); }); </script> <table id="gridTable"> </table> <div id="gridPager"> </div> jqgrid有几个较为关键的属性:
上面这个例子的效果如下图: 2. jqgrid的server data之loadonce方式实际的应用中数据都来源于后端,local方式基本不会使用。jqgrid中有一种loadonce的方式,当然后台提供所有的数据,分页、排序功能都由客户端自己去实现。数据少的时候用这种方式是最为快速的,毕竟只做一次请求后台除了输出数据外不需要再写其他的代码了。 请看代码示例: <script type="text/javascript"> $(document).ready(function() { $("#gridTable").jqGrid({ url : 'data/test.json', datatype: 'json', height: 150, rowNum: 10, rowList: [10, 20, 30], colNames: ['Inv No', 'Date', 'Client', 'Amount', 'Tax', 'Total', 'Notes'], colModel: [ { name: 'id', index: 'id', width: 60, sorttype: "int" }, { name: 'invdate', index: 'invdate', width: 90, sorttype: "date", formatter: "date" }, { name: 'name', index: 'name', width: 100 }, { name: 'amount', index: 'amount', width: 80, align: "right", sorttype: "float", formatter: "number" }, { name: 'tax', index: 'tax', width: 80, align: "right", sorttype: "float" }, { name: 'total', index: 'total', width: 80, align: "right", sorttype: "float" }, { name: 'note', index: 'note', width: 150, sortable: false } ], loadonce: true, sortname: 'id', sortorder: 'desc', pager: "#gridPager", viewrecords: true, caption: "Manipulating Array Data" }); }); </script> <table id="gridTable"> </table> <div id="gridPager"> </div> 这段代码和local data的形式中不同之处在于: (1). url:指定了请求的数据源。(test.json文件的内容和第1个例子中的mydata 内容一样)
OK,编译运行,但是结果却没有出现例子1中的效果图,jqgrid里面完全没有数据显示。
这时候jqgrid中一个更为关键的属性出现了,jsonReader。既然指定了数据格式为json,那么后端传过来的数据格式总不能我说什么就是什么吧,{"id":1, "name":"keepfool"}和{1,"keepfool"}都是正确的json数据,当传到前端时,前端怎么会知道要匹配哪一种形式?jsonReader顾名思义,就是用来读取json的,当然也要给它定个规矩。 让我们来看看http://www.trirand.com/jqgridwiki/doku.php?id=wiki:retrieving_data#json_data中默认的json格式是怎么样的吧 当没有设置jsonReader属性时,提供的json格式应该是下面这种形式的: 它让你指定total,page,records属性(分别对应总页数、当前页、记录总数);rows属性,还必须指定id和cell属性,cell属性里面仅仅是单元格的值,还不能包括列名。如果按照默认的jsonReader来读取数据,你可能会写出如下构造json的代码: public class MyOrder : IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "application/json"; string sql = "select top 100 OrderID,CustomerID,ShipName,OrderDate from Orders "; DataTable dt = SqlHelper.ExecuteDataset(sql).Tables[0]; IList<object> rowObjects = new List<object>(); // 每页显示记录数 int pageSize = 10; // 记录总数 int rowCount = dt.Rows.Count; // 列数 int columnCount = dt.Columns.Count; // 总页数 int pageCount = rowCount%pageSize == 0 ? rowCount/pageSize : rowCount/pageSize + 1; int ID = 1; foreach (DataRow dr in dt.Rows) { var cellValue = new string[columnCount]; for (var i = 0; i < cellValue.Length; i++) { cellValue[i] = dr[i].ToString(); } // 创建row对象 var rowObj = new { id = ID, cell = cellValue }; rowObjects.Add(rowObj); ID++; } var resultObj = new { total = pageCount, // 总页数 page = 1, // 由于客户端是loadonce的,page也可以不指定 records = rowCount, // 总记录数 rows = rowObjects // 数据 }; string json = JsonConvert.SerializeObject(resultObj); context.Response.Write(json); } public bool IsReusable { get { return false; } } } 请求页面LoadOnceOrders.aspx效果:
但是这里存在一个小bug,下面的分页按钮不起作用了,当点击排序或者选择每页显示记录数时,分页按钮又可以用了。这个bug仅在loadonce为true时会出现。 在http://www.trirand.com/jqgridwiki/doku.php?id=wiki:options页面中也对loadonce属性有所说明 3. jqgrid的jsonReader上面的例子中没有设置jsonReader属性,那么就得按照默认的jsonReader提供json数据。上面的json数据会让我们感觉有一些怪异,rows属性中的id和cell我们不需要,total应该表示为pagecount, records应该表示为total在语义上更易读通,而且row中的每一列都应当是键值对这种形式。 寻常情况下我们提供的json格式应该是这样的: { "pagecount":10, "pageindex":1, "total":100, "rows":[ { "id":1, "name":"keepfool" }, { "id":2, "name":"pai" } ... ] } pagecount表示总页数,pageindex表示当前页,total表示总记录数,rows表示记录。既然这样,我们的jsonReader就得改写,而且后台也应当提供这样的数据。 LoadOnceOrder2.aspx页面的jsonReader(其他设置和LoadOnceOrders.aspx页面一致) jsonReader: { root: "rows", page: "pageindex", total: "pagecount", records: "total", repeatitems: false, id: "0" } 请注意这里的repeatitems属性,当repeatitems=false时,jqgrid会根据返回的json数据搜索列名,这个列名对应colModel中的名字
public class MyOrder2 : IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "application/json"; string sql = "select top 100 OrderID,CustomerID,ShipName,OrderDate from Orders "; DataTable dt = SqlHelper.ExecuteDataset(sql).Tables[0]; // 每页显示记录数 int pageSize = 10; // 记录总数 int rowCount = dt.Rows.Count; // 总页数 int pageCount = rowCount % pageSize == 0 ? rowCount / pageSize : rowCount / pageSize + 1; var resultObj = new DataResult { // 总页数 PageCount = pageCount, // 当前页 PageIndex = 1, // 总记录数 Total = rowCount, // 数据 Data = dt }; string resultJson = JsonHelper.Serialize(resultObj); context.Response.Write(resultJson); } public bool IsReusable { get { return false; } } } DataResult类的代码很简单: /// <summary> /// 数据结果 /// </summary> public class DataResult { |
请发表评论