在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
第一次看到ACE模板,有种感动,有种相见恨晚的感觉,于是迅速来研究。它本身是基于bootstrap和jqueryui,但更nice,整合之后为后台开发节省了大量时间。 发现虽然不是完美,整体效果还是不错,特此分享给园友。这一节先讲其中的Jqgrid。按照国际惯例,先上两张图。
集成了button,form,treeview以及日历,时间轴、chart等控件,非常丰富。下面是Jqgrid在MVC中的使用。 jqgrid的加载,排序,查找都是基于后台方法,不是在内存中完成,但也有一些小坑。下面一一道来。 一、引入ace模板 ace本身考虑了对ie的兼容,加上bootstrap和jqueryui所以引入的样式和脚本文件比较多。我拿掉了一下googlefont的链接,请求太慢了,你懂的。现在MVC最关心的就是RenderBody的位置。在page-content下的Row,也可以将page-header放入子页面中去,自己多写几个元素,这个就在于你自己的选择了。 <div class="page-content"> <div class="page-header"> <h1> <span>控制台</span> <small> <i class="icon-double-angle-right"></i> <span>查看</span> </small> </h1> </div><!-- /.page-header --> <div class="row"> <div class="col-xs-12"> <!-- PAGE CONTENT BEGINS --> @RenderBody() <!-- PAGE CONTENT ENDS --> </div><!-- /.col --> </div><!-- /.row --> </div><!-- /.page-content --> 全部的layout.cshtml
View Code
二、引入Jqgrid 如果你的表格比较多,建议你做一个分部试图,重复利用,我的partview JqgridInit.cshtml 如下, <link rel="stylesheet" href="~/Content/CSS/ui.jqgrid.css" /> <script src="~/Content/Js/jqGrid/jquery.jqGrid.min.js"></script> <script src="~/Content/Js/jqGrid/i18n/grid.locale-en.js"></script> <style> #pager2 { height: 40px; } .FormGrid ,#DelTb1_list2{ position: relative; overflow: visible; float: left; } .ui-jqgrid-sortable { height: 30px !important; } </style> <table ></table> <div ></div> <span class="errorinfo"></span> list用来呈现数据,pager用来分页,errorinfo用来提示错误。jqgrid,涉及的配置比较多。需要后台代码的全面的支持,所以在介绍配置之前,先介绍下模型和仓库。 1.Product: 我们需要呈现的一个是一个产品,有很多不同的价格及其他,这些都将成为表格的列名。
View Code
2.ProductRepository (仓库真的很好,独立了业务逻辑,可测试,复用快),add、remove、update不用讲了,主要讲一讲排序。 1)排序查询的意义在于根据不同的属性进行排序。 public class ProductRepository:IProductRepository { private readonly XNDb _db = new XNDb(); //.... public IEnumerable<Product> Find(string sort = "asc", string property = "ProductName", int skip = 0, int take = 10) { var propertyInfo = typeof(Product).GetProperty(property);//反射出这个属性 Func<Product, object> expn = e => propertyInfo.GetValue(e, null);//委托 var rawpros = _db.Products; IEnumerable<Product> pros = sort == "asc" ? rawpros.OrderBy(expn).Skip(skip).Take(take).ToArray() : rawpros.OrderByDescending(expn).Skip(skip).Take(take).ToArray();//分页排序 return pros; } 在只考虑排序的情况下,控制器的代码就相对简单: public JsonResult GetAllPros( string sord = "asc", string sidx = "ProductName",int page = 1, int rows = 10) { var pros = _repository.Find(sord, switchSidx(sidx), (page - 1) * rows, rows); var objpros = new List<object>(pros); var jsonData = JqGridModel.GridData(page, rows, _repository.Count, objpros); return Json(jsonData, JsonRequestBehavior.AllowGet); } 如果涉及到复杂些的查询,等于不等于,包含之类的,会多了后面mark部分的参数,这里我用很笨的办法实现了单列查询,也就就是根据包含、等于、不等于先查出来,再排序,如果是多重查询,大家可以参考博客:http://www.codeproject.com/Articles/58357/Using-jqGrid-s-search-toolbar-with-multiple-filter public JsonResult GetAllPros( string sord = "asc", string sidx = "ProductName",int page = 1, int rows = 10, bool _search = false,string searchField="", string searchOper="", string searchString="") { var rawpros = GetRawPros(_search, searchField, searchOper, searchString); var propertyInfo = typeof(Product).GetProperty(switchSidx(sidx)); Func<Product, object> expn = e => propertyInfo.GetValue(e, null); var enumerable = rawpros as Product[] ?? rawpros.ToArray(); IEnumerable<Product> pros = sord == "asc" ? enumerable.OrderBy(expn).Skip((page - 1) * rows).Take(rows).ToArray() : enumerable.OrderByDescending(expn).Skip((page - 1) * rows).Take(rows).ToArray(); var objpros = new List<object>(pros); var jsonData = JqGridModel.GridData(page, rows, enumerable.Count(), objpros); return Json(jsonData, JsonRequestBehavior.AllowGet); }
需要说明的是,这里的switchsidx就是将中文列名转为对象属性名,一堆case语句,然后JqgridModel的getdata,是jqgrid定义好的一种json格式,包含了每页行数和总页数等信息,因为前段的每页行数是可以变化的。 public class JqGridModel { /// <summary> /// Grids the data. /// </summary> /// <param name="page1">当前页数.</param> /// <param name="rows">每页显示数目.</param> /// <param name="total"></param> /// <param name="objects">集合对象</param> /// <returns>System.Object.</returns> public static object GridData(int page1, int rows, int total, IEnumerable<object> objects) { int pageSize = rows; var totalPages = (int)Math.Ceiling((float)total / pageSize); //可根据具体情况,实现排序。 var jsonData = new { total = totalPages, page = page1, records = total, rows = objects.ToArray() }; return jsonData; } } 2)需要一个新增:(记住返回json的时候要allowGet,不然可能造成添加失败,其他地方同理) [HttpPost] public ActionResult Create(Product product) { _repository.Add(product); var fu = _repository.FindByName(product.ProductName); return Json(fu, JsonRequestBehavior.AllowGet); } 3)编辑和删除:这里的编辑有三个参数,一个对象,一个操作,一个id,id是个鸡肋,居然返回的是table的行号(会随着排序变化),oper可能是add,del,这里我只用到了edit,del传回的id尝试改变它为对象的id,但没成功。用了因外一种方式实现删除。 [HttpPost] public ActionResult Edit(Product pro, string oper, int id) { if (oper == "edit") { _repository.Update(pro); pro.CreateTime = DateTime.Now; } return Json(pro, JsonRequestBehavior.AllowGet); } [HttpPost] public ActionResult Delete(int id) { _repository.Remove(id); return Json(id, JsonRequestBehavior.AllowGet); ; } 有了这四个方法就ok了。下面来讲配置。先打个预防针,主要关心两个方法,一个设置table,一个设置分页。然后代码比较长..... 希望没有打消你驾驭它的渴望。 全部控制器代码:包含了分类的一些,道理一样
View Code
1)table的设置 jQuery("#list").jqGrid({ url: '/Product/GetAllPros', //获取数据源 datatype: "json", colNames: ['操作', 'ProductId', '类别', '品牌', '型号', '规格', '专柜', '莎莎', '卓越', '卡莱美', '雅施', '万宁', '屈臣氏', '药店', '其他', '更新时间'], //定义列名 colModel: [ //name 是对应我们的Product模型的属性,Index可以为中文也可以为英文,不必于上面colnames对应,顺序对就行了。查询的时候传到后台的是index。 { name: 'myac', index: '操作', width: 60, fixed: true, sortable: false, resize: false, formatter: 'actions', formatoptions: { keys: true, delOptions: { recreateForm: true, beforeShowForm: beforeDeleteCallback, }, } }, 形成样子如下: colModel涉及的配置较多,不同的字段有不同的呈现,可以参考博客 http://www.cnblogs.com/huozhicheng/archive/2012/11/20/2778649.html 2)pager 用来形成分页和集成一些操作。 jQuery("#list").jqGrid('navGrid', '#pager2', { ,但这个删除图标是我代码加上去的。 edit: true, editicon: 'icon-pencil blue', add: true, addicon: 'icon-plus-sign purple', del: false, delicon: 'icon-trash red', search: true, searchicon: 'icon-search orange', refresh: true, refreshicon: 'icon-refresh green', view: false, viewicon: 'icon-zoom-in grey', }, { //eidt url: '/Product/Edit', mtype: 'POST', afterSubmit: function (xhr, postdata) { var id = $("#list2").jqGrid('getGridParam', 'selrow'); jQuery("#list2").jqGrid('setRowData', id, postdata); }, closeAfterEdit: true, closeOnEscape: true }, { //add recreateForm: true, url: '/Product/Create', mtype: 'POST', afterSubmit: function (xhr, postdata) { var id = $("#list2").jqGrid('getGridParam', 'selrow'); jQuery("#list2").jqGrid('addRowData', postdata.Id, postdata); return [true, 'successfule!', false]; }, closeAfterAdd: true }, { //delete 此处无效 recreateForm: true, url: '/Product/Delete', mtype: 'POST', beforeShowForm: function (e) { var form = $(e[0]); if (form.data('styled')) return false; form.closest('.ui-jqdialog').find('.ui-jqdialog-titlebar').wrapInner('<div class="widget-header" />'); styleDeleteForm(form); form.data('styled', true); return true; }, afterSubmit: function (xhr, postdata) { var consoleDlg = $("#list2"); var selectedRowIds = $("#list2").jqGrid("getGridParam", "selarrrow"); var len = selectedRowIds.length; for (var i = 0; i < len ; i++) { $("#list2").jqGrid("delRowData", selectedRowIds[0]); } }, closeAfterDel: true }, { //search recreateForm: true, afterShowSearch: function(e){ var form = $(e[0]); form.closest('.ui-jqdialog').find('.ui-jqdialog-title').wrap('<div class="widget-header" />') styleSearchForm(form); }, afterRedraw: function(){ styleSearchFilters($(this)); } , // multipleSearch: true, closeAfterSearch: true }, { //view } ); 在下面加入按钮的方法以及执行删除:jquery2.0中的绑定写法有些不同,也就是on的用法。 function updatePagerIcons() { //... var x = $("#pager2_left").find("#coco"); if (x.length == 0) { $("#pager2_left table tbody>tr").prepend("<td class='ui-pg-button ui-corner-all' title data-original-title='Remove a row'><div id='coco' class='ui-pg-div'>" + "<span class='ui-icon icon-trash blue'></span></div></td>"); } } //绑定事件 执行删除 $("#pager2_left table tbody>tr").on("click", '#coco', function () { var selectedRowIds = $("#list2").jqGrid("getGridParam", "selarrrow"); var len = selectedRowIds.length; if (len != 0) { if (confirm("确定要删除选中项?")) { for (var i = 0; i < len; i++) { var rowData = $("#list2").jqGrid('getRowData', selectedRowIds[i]); $.post('/Product/Delete', { id: rowData.ProductId }, function (data) { $("#list2").jqGrid("delRowData", selectedRowIds[0]); }); } } } else { $.infoShow("未勾选", 0); } }); 形成这个样子: 全部前台代码:
View Code
至此基本告成,还有些可以优化。
如果本文对你有帮助,请霸气的支持下 :) tks~ 需要源码的同学,请留邮箱。备注:数据库是EntityFramework + CE4.0,账户密码都是:admin 模板源码:http://pan.baidu.com/s/1gdEGg2v 参考博客: 参数设定 http://www.cnblogs.com/younggun/archive/2012/08/27/2657922.html jqgridDemo:http://www.trirand.com/blog/jqgrid/jqgrid.html 多重查询:http://www.codeproject.com/Articles/58357/Using-jqGrid-s-search-toolbar-with-multiple-filter 其他后台模板:http://www.tystudio.net/2013/03/11/back-manage-system-template/
源码笔记
第一次看到ACE模板,有种感动,有种相见恨晚的感觉,于是迅速来研究。它本身是基于bootstrap和jqueryui,但更nice,整合之后为后台开发节省了大量时间。 发现虽然不是完美,整体效果还是不错,特此分享给园友。这一节先讲其中的Jqgrid。按照国际惯例,先上两张图。
集成了button,form,treeview以及日历,时间轴、chart等控件,非常丰富。下面是Jqgrid在MVC中的使用。 jqgrid的加载,排序,查找都是基于后台方法,不是在内存中完成,但也有一些小坑。下面一一道来。 一、引入ace模板 ace本身考虑了对ie的兼容,加上bootstrap和jqueryui所以引入的样式和脚本文件比较多。我拿掉了一下googlefont的链接,请求太慢了,你懂的。现在MVC最关心的就是RenderBody的位置。在page-content下的Row,也可以将page-header放入子页面中去,自己多写几个元素,这个就在于你自己的选择了。 <div class="page-content"> <div class="page-header"> <h1> <span>控制台</span> <small> <i class="icon-double-angle-right"></i> <span>查看</span> </small> </h1> </div><!-- /.page-header --> <div class="row"> <div class="col-xs-12"> <!-- PAGE CONTENT BEGINS --> @RenderBody() <!-- PAGE CONTENT ENDS --> </div><!-- /.col --> </div><!-- /.row --> </div><!-- /.page-content --> 全部的layout.cshtml
View Code
二、引入Jqgrid 如果你的表格比较多,建议你做一个分部试图,重复利用,我的partview JqgridInit.cshtml 如下, <link rel="stylesheet" href="~/Content/CSS/ui.jqgrid.css" /> <script src="~/Content/Js/jqGrid/jquery.jqGrid.min.js"></script> <script src="~/Content/Js/jqGrid/i18n/grid.locale-en.js"></script> <style> #pager2 { height: 40px; } .FormGrid ,#DelTb1_list2{ position: relative; overflow: visible; float: left; } .ui-jqgrid-sortable { height: 30px !important; } </style> <table ></table> <div ></div> <span class="errorinfo"></span> list用来呈现数据,pager用来分页,errorinfo用来提示错误。jqgrid,涉及的配置比较多。需要后台代码的全面的支持,所以在介绍配置之前,先介绍下模型和仓库。 1.Product: 我们需要呈现的一个是一个产品,有很多不同的价格及其他,这些都将成为表格的列名。
View Code
2.ProductRepository (仓库真的很好,独立了业务逻辑,可测试,复用快),add、remove、update不用讲了,主要讲一讲排序。 1)排序查询的意义在于根据不同的属性进行排序。 public class ProductRepository:IProductRepository { private readonly XNDb _db = new XNDb(); //.... public IEnumerable<Product> Find(string sort = "asc", string property = "ProductName", int skip = 0, int take = 10) { var propertyInfo = typeof(Product).GetProperty(property);//反射出这个属性 Func<Product, object> expn = e => propertyInfo.GetValue(e, null);//委托 var rawpros = _db.Products; IEnumerable<Product> pros = sort == "asc" ? rawpros.OrderBy(expn).Skip(skip).Take(take).ToArray() : rawpros.OrderByDescending(expn).Skip(skip).Take(take).ToArray();//分页排序 return pros; } 在只考虑排序的情况下,控制器的代码就相对简单: public JsonResult GetAllPros( string sord = "asc", string sidx = "ProductName",int page = 1, int rows = 10) { var pros = _repository.Find(sord, switchSidx(sidx), (page - 1) * rows, rows); var objpros = new List<object>(pros); var jsonData = JqGridModel.GridData(page, rows, _repository.Count, objpros); return Json(jsonData, JsonRequestBehavior.AllowGet); } 如果涉及到复杂些的查询,等于不等于,包含之类的,会多了后面mark部分的参数,这里我用很笨的办法实现了单列查询,也就就是根据包含、等于、不等于先查出来,再排序,如果是多重查询,大家可以参考博客:http://www.codeproject.com/Articles/58357/Using-jqGrid-s-search-toolbar-with-multiple-filter public JsonResult GetAllPros( string sord = "asc", string sidx = "ProductName",int page = 1, int rows = 10, bool _search = false,string searchField="", string searchOper="", string searchString="") { var rawpros = GetRawPros(_search, searchField, searchOper, searchString); var propertyInfo = typeof(Product).GetProperty(switchSidx(sidx)); Func<Product, object> expn = e => propertyInfo.GetValue(e, null); var enumerable = rawpros as Product[] ?? rawpros.ToArray(); IEnumerable<Product> pros = sord == "asc" ? enumerable.OrderBy(expn).Skip((page - 1) * rows).Take(rows).ToArray() : enumerable.OrderByDescending(expn).Skip((page - 1) * rows).Take(rows).ToArray(); var objpros = new List<object>(pros); var jsonData = JqGridModel.GridData(page, rows, enumerable.Count(), objpros); return Json(jsonData, JsonRequestBehavior.AllowGet); }
需要说明的是,这里的switchsidx就是将中文列名转为对象属性名,一堆case语句,然后JqgridModel的getdata,是jqgrid定义好的一种json格式,包含了每页行数和总页数等信息,因为前段的每页行数是可以变化的。 public class JqGridModel { /// <summary> /// Grids the data. /// </summary> /// <param name="page1">当前页数.</param> /// <param name="rows">每页显示数目.</param> /// <param name="total"></param> /// <param name="objects">集合对象</param> /// <returns>System.Object.</returns> public static object GridData(int page1, int rows, int total, IEnumerable<object> objects) { int pageSize = rows; var totalPages = (int)Math.Ceiling((float)total / pageSize); //可根据具体情况,实现排序。 var jsonData = new { total = totalPages, page = page1, records = total, rows = objects.ToArray() }; return jsonData; } } 2)需要一个新增:(记住返回json的时候要allowGet,不然可能造成添加失败,其他地方同理) [HttpPost] public ActionResult Create(Product product) { _repository.Add(product); var fu = _repository.FindByName(product.ProductName); return Json(fu, JsonRequestBehavior.AllowGet); } 3)编辑和删除:这里的编辑有三个参数,一个对象,一个操作,一个id,id是个鸡肋,居然返回的是table的行号(会随着排序变化),oper可能是add,del,这里我只用到了edit,del传回的id尝试改变它为对象的id,但没成功。用了因外一种方式实现删除。 [HttpPost] public ActionResult Edit(Product pro, string oper, int id) { if (oper == "edit") { _repository.Update(pro); pro.CreateTime = DateTime.Now; } return Json(pro, JsonRequestBehavior.AllowGet); } [HttpPost] public ActionResult Delete(int id) { _repository.Remove(id); return Json(id, JsonRequestBehavior.AllowGet); ; } 有了这四个方法就ok了。下面来讲配置。先打个预防针,主要关心两个方法,一个设置table,一个设置分页。然后代码比较长..... 希望没有打消你驾驭它的渴望。 全部控制器代码:包含了分类的一些,道理一样
View Code
1)table的设置 jQuery("#list").jqGrid({ url: '/Product/GetAllPros', //获取数据源 datatype: "json", colNames: ['操作', 'ProductId', '类别', '品牌', '型号', '规格', '专柜', '莎莎', '卓越', '卡莱美', '雅施', '万宁', '屈臣氏', '药店', '其他', '更新时间'], //定义列名 colModel: [ //name 是对应我们的Product模型的属性,Index可以为中文也可以为英文,不必于上面colnames对应,顺序对就行了。查询的时候传到后台的是index。 { name: 'myac', index: '操作', width: 60, fixed: true, sortable: false, resize: false, formatter: 'actions', formatoptions: { keys: true, delOptions: { recreateForm: true, beforeShowForm: beforeDeleteCallback, }, } }, 形成样子如下: colModel涉及的配置较多,不同的字段有不同的呈现,可以参考博客 http://www.cnblogs.com/huozhicheng/archive/2012/11/20/2778649.html 2)pager 用来形成分页和集成一些操作。 jQuery("#list").jqGrid('navGrid', '#pager2', { ,但这个删除图标是我代码加上去的。 edit: true, editicon: 'icon-pencil blue', add: true, addicon: 'icon-plus-sign purple', del: false, delicon: 'icon-trash red', search: true, searchicon: 'icon-search orange', refresh: true, refreshicon: 'icon-refresh green', view: false, viewicon: 'icon-zoom-in grey', }, { //eidt url: '/Product/Edit', mtype: 'POST', afterSubmit: function (xhr, postdata) { var id = $("#list2").jqGrid('getGridParam', 'selrow'); jQuery("#list2").jqGrid('setRowData', id, postdata); }, closeAfterEdit: true, closeOnEscape: true }, { //add recreateForm: true, url: '/Product/Create', mtype: 'POST', afterSubmit: function (xhr, postdata) { var id = $("#list2").jqGrid('getGridParam', 'selrow'); jQuery("#list2").jqGrid('addRowData', postdata.Id, postdata); return [true, 'successfule!', false]; }, closeAfterAdd: true }, { //delete 此处无效 recreateForm: true, url: '/Product/Delete', mtype: 'POST', beforeShowForm: function (e) { var form = $(e[0]); if (form.data('styled')) return false; form.closest('.ui-jqdialog').find('.ui-jqdialog-titlebar').wrapInner('<div class="widget-header" />'); styleDeleteForm(form); form.data('styled', true); return true; }, afterSubmit: function (xhr, postdata) { var consoleDlg = $("#list2"); var selectedRowIds = $("#list2").jqGrid("getGridParam", "selarrrow"); var len = selectedRowIds.length; for (var i = 0; i < len ; i++) { $("#list2").jqGrid("delRowData", selectedRowIds[0]); } }, closeAfterDel: true }, { //search recreateForm: true, afterShowSearch: function(e){ var form = $(e[0]); form.closest('.ui-jqdialog').find('.ui-jqdialog-title').wrap('<div class="widget-header" />') styleSearchForm(form); }, afterRedraw: function(){ styleSearchFilters($(this)); } , // multipleSearch: true, closeAfterSearch: true }, { //view } ); 在下面加入按钮的方法以及执行删除:jquery2.0中的绑定写法有些不同,也就是on的用法。 function updatePagerIcons() { //... var x = $("#pager2_left").find("#coco"); if (x.length == 0) { $("#pager2_left table tbody>tr").prepend("<td class='ui-pg-button ui-corner-all' title data-original-title='Remove a row'><div id='coco' class='ui-pg-div'>" + "<span class='ui-icon icon-trash blue'></span></div></td>"); } } //绑定事件 执行删除 $("#pager2_left table tbody>tr").on("click", '#coco', function () { var selectedRowIds = $("#list2").jqGrid("getGridParam", "selarrrow"); var len = selectedRowIds.length; if (len != 0) { if (confirm("确定要删除选中项?")) { for (var i = 0; i < len; i++) { var rowData = $("#list2").jqGrid('getRowData', selectedRowIds[i]); $.post('/Product/Delete', { id: rowData.ProductId }, function (data) { $("#list2").jqGrid("delRowData", selectedRowIds[0]); }); } } } else { $.infoShow("未勾选", 0); } }); 形成这个样子: 全部前台代码:
View Code
至此基本告成,还有些可以优化。
如果本文对你有帮助,请霸气的支持下 :) tks~ 需要源码的同学,请留邮箱。备注:数据库是EntityFramework + CE4.0,账户密码都是:admin 模板源码:http://pan.baidu.com/s/1gdEGg2v 参考博客: 参数设定 http://www.cnblogs.com/younggun/archive/2012/08/27/2657922.html jqgridDemo:http://www.trirand.com/blog/jqgrid/jqgrid.html 多重查询:http://www.codeproject.com/Articles/58357/Using-jqGrid-s-search-toolbar-with-multiple-filter 其他后台模板:http://www.tystudio.net/2013/03/11/back-manage-system-template/
|
请发表评论