Asp.Net MVC中使用ACE模板之Jqgrid

 

第一次看到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

 

二、引入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 id="list"></table>
<div id="pager"></div>
<span class="errorinfo"></span>

list用来呈现数据,pager用来分页,errorinfo用来提示错误。jqgrid,涉及的配置比较多。需要后台代码的全面的支持,所以在介绍配置之前,先介绍下模型和仓库。

1.Product: 我们需要呈现的一个是一个产品,有很多不同的价格及其他,这些都将成为表格的列名。

 

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,一个设置分页。然后代码比较长..... 希望没有打消你驾驭它的渴望。

全部控制器代码:包含了分类的一些,道理一样

 

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, },
}
},
//详细的字段配置信息请见博客:http://www.cnblogs.com/huozhicheng/archive/2012/11/20/2778649.html
{ name: 'ProductId', index: 'ProductId', hidden: true, editable: true },
{ name: 'Category', index: '类别', editable: true, edittype: 'select', editoptions: { dataUrl: "/Product/CategorySelectList" }, searchoptions: { sopt: ['eq', 'ne', 'cn'] } },
{ name: 'Brand', index: '品牌', editable: true, editrules: { required: false }, searchoptions: { sopt: ['eq', 'ne', 'cn'] } },
{ name: 'ProductName', index: '型号', editable: true, editrules: { required: true }, searchoptions: { sopt: ['eq', 'ne', 'cn'] } },
{ name: 'Standard', index: '规格', editable: true, edittype: 'textarea', searchoptions: { sopt: ['eq', 'ne', 'cn'] } },
{ name: 'ZhuanGui', index: '专柜', editable: true, width: 60, searchoptions: { sopt: ['eq', 'ne', 'cn'] } },//formatter: 'integer', formatter: 'integer',
{ name: 'SaSaPrice', index: '莎莎', editable: true,width: 60, searchoptions: { sopt: ['eq', 'ne', 'cn'] } },
{ name: 'ZhuoyuePrice', index: '卓越', editable: true, formatter: 'integer', width: 60, searchoptions: { sopt: ['eq', 'ne', 'cn'] } },
{ name: 'KaLaiPrice', index: '卡莱美', editable: true, formatter: 'integer', width: 60, searchoptions: { sopt: ['eq', 'ne', 'cn'] } },
{ name: 'YaShi', index: '雅施', editable: true, formatter: 'integer', width: 60, searchoptions: { sopt: ['eq', 'ne', 'cn'] } },
{ name: 'WanningPrice', index: '万宁', editable: true, formatter: 'integer', width: 60, searchoptions: { sopt: ['eq', 'ne', 'cn'] } },
{ name: 'QuchengshiPrice', index: '屈臣氏', editable: true, formatter: 'integer', width: 60, searchoptions: { sopt: ['eq', 'ne', 'cn'] } },
{ name: 'DrugstorePrice', index: '药店', editable: true, formatter: 'integer', width: 60, searchoptions: { sopt: ['eq', 'ne', 'cn'] } },
{ name: 'Others', index: '其他', editable: true, edittype: 'textarea', searchoptions: { sopt: ['eq', 'ne', 'cn'] } },
{
name: 'CreateTime', index: '更新时间', width: 200, formatter: 'date', //时间格式显示
formatoptions: { srcformat: 'Y-m-d H:i:s', newformat: 'Y-m-d H:i:s', searchoptions: { sopt: ['eq', 'ne', 'cn'] } }
}
],
rowNum: 10,
rowList: [10, 20, 30],
sortorder: "asc",
pager: '#pager2',
sortname: 'ProductName',
viewrecords: true,
caption: "产品明细",
autowidth: true,
multiselect: true,
height: 180,
gridComplete: function () {
var icons = $(".ui-icon-trash");//隐藏删除键
icons.hide();//我隐藏了删除键 因为id的问题
//var ids = jQuery("#list2").jqGrid('getDataIDs');
//for (var i = 0; i < ids.length; i++) {
// be = "<span class='ui-icon ui-icon-pencil'></span>";//修改
// se = "<span class='ui-icon ui-icon-trash'></span>";//删除
// ce = "<span class='icon-ok ui-icon'></span>";//删除
// jQuery("#list2").jqGrid('setRowData', ids[i], { act: be + se + ce });
//}
//这个部分是可以添加定义的按钮,自己用脚本去实现。
},
loadComplete: function () {
$("#grid-table").hide();
var table = this;
enableTooltips(table);
updatePagerIcons(table);
}, editurl: "/Product/Edit", //编辑的地址 操作栏触发的操作都会丢到这个action中响应。 add edit del
//改变传id的方法无效!!!!
serializeDelData: function (postdata) {
var rowdata = jQuery('#list2').getRowData(postdata.id);
return { id: postdata.id, oper: postdata.oper, user: rowdata };
}
//edit del
});

形成样子如下:

colModel涉及的配置较多,不同的字段有不同的呈现,可以参考博客http://www.cnblogs.com/huozhicheng/archive/2012/11/20/2778649.html

2)pager 用来形成分页和集成一些操作。

   jQuery("#list").jqGrid('navGrid', '#pager2', {
//调整ui 也就是我们看到的:

 ,但这个删除图标是我代码加上去的。
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);
}
});

形成这个样子:

全部前台代码:

 

至此基本告成,还有些可以优化。

如果本文对你有帮助,请霸气的支持下    :)  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/

 
 
分类: JqueryMVC源码笔记

ACE模板之Jqgrid的更多相关文章

  1. Asp.Net MVC中使用ACE模板之Jqgrid

    第一次看到ACE模板,有种感动,有种相见恨晚的感觉,于是迅速来研究.它本身是基于bootstrap和jqueryui,但更nice,整合之后为后台开发节省了大量时间. 发现虽然不是完美,整体效果还是不 ...

  2. JS组件系列——基于Bootstrap Ace模板的菜单和Tab页效果分享(你值得拥有)

    前言:最近园子里多了许多谈语言.谈环境.谈逼格(格局)的文章,看看笑笑过后,殊不知其实都是然并卵.提升自己的技术才是王道.之前博主分享过多篇bootstrap组件的文章,引起了很多园友的关注和支持,看 ...

  3. hangfire+bootstrap ace 模板实现后台任务管理平台

    前言 前端时间刚开始接触Hangfire就翻译了一篇官方的教程[翻译+山寨]Hangfire Highlighter Tutorial,后来在工作中需要实现一个异步和定时执行的任务管理平台,就结合bo ...

  4. JS组件系列——基于Bootstrap Ace模板的菜单Tab页效果优化

    前言:之前发表过一篇  JS组件系列——基于Bootstrap Ace模板的菜单和Tab页效果分享(你值得拥有) ,收到很多园友的反馈,当然也包括很多诟病,因为上篇只是将功能实现了,很多细节都没有处理 ...

  5. 值得分享的Bootstrap Ace模板实现菜单和Tab页效果(转)

    Ace模板地址:http://code.google.com/p/ace-engine/wiki/AceTemplate(有时会打不开) Ace英文官网:http://wrapbootstrap.co ...

  6. JS组件系列——基于Bootstrap Ace模板的菜单和Tab页效果

    Ace模板地址:http://code.google.com/p/ace-engine/wiki/AceTemplate(有时会打不开) Ace英文官网:http://wrapbootstrap.co ...

  7. 基于Bootstrap Ace模板+bootstrap.addtabs.js的菜单

    这几天研究了基于bootstrap Ace模板+bootstra.addtabs.js实现菜单的效果 参考了这个人的博客 https://www.cnblogs.com/landeanfen/p/76 ...

  8. ace模板dataTables_length控制是否显示分页

    默认的ace中配置的是7列之后才显示分页的,其实是可控的,如下: aoColumns这个参数的含义: 排序控制 $(document).ready(function() {$('#example'). ...

  9. bootstrap-paginator 分页插件笔记

    [MVC]bootstrap-paginator 分页插件笔记   bootstrap-paginator基于bootstrap框架,使用起来非常简单.官网:http://harttle.github ...

随机推荐

  1. 在 Windows Server 2008 R2 上安装 IIS 7.5

    原文 在 Windows Server 2008 R2 上安装 IIS 7.5 默认情况下,Windows Server(R) 2008 R2 上不安装 IIS 7.5.可以使用服务器管理器中的“添加 ...

  2. SQL Server 2012 复制(发布订阅的研究)

    原文:SQL Server 2012 复制(发布订阅的研究) 已实现发布订阅功能,可以实现局域网内双击备份. 一.注意事项: a) 使用[事务复制]功能 b) 必须是相同的SqlServer 帐号和密 ...

  3. hdu 3695 Computer Virus on Planet Pandora(AC自己主动机)

    题目连接:hdu 3695 Computer Virus on Planet Pandora 题目大意:给定一些病毒串,要求推断说给定串中包括几个病毒串,包括反转. 解题思路:将给定的字符串展开,然后 ...

  4. Winform 实现像菜单一样弹出层

    原文:Winform 实现像菜单一样弹出层 在实际工作中,如果能像菜单一样弹出自定义内容,会方便很多,比如查询时,比如下拉列表显示多列信息时,比如在填写某个信息需要查看一些信息树时.这个时候自定义弹出 ...

  5. SQL Server---触发

    今天的第一次SQL Server触发感觉很方便,本文将向您介绍一个简单的SQL Server触发器和简单的使用. 我将确定其.原理.使用细节都是关于. 定义 触发器(trigger)是个特殊的存储过程 ...

  6. CreateCompatibleDC工作原理

    WindowsGDI的接口没提供这种功能机制.仅仅能是先通过CreateCompatibleDC 创建一个与显示器设备内容兼容的内存设备内容.用SelectObject将位图选入内存设备内容,再用Bi ...

  7. 使用Maven在Eclipse中创建Web项目[转]

    一.新建 Maven Web项目 1.新建Maven Project new project-->选择 Maven Project --> 下一步 选择工作空间 -->下一步 在Fi ...

  8. 1006-HBase操作实战(JAVA API状态)

    一.准备阶段 开发环境: hadoop: hadoop -2.4.0 hbase: hbase -0.94.11-security eclipse:Juno Service Release 2 二.创 ...

  9. error C3130: 内部编译器错误: 未能将插入的代码块写入PDB

    近期编译cocos2d-x的test突然出现这个错误,又一次编译也无法解决. 一般出现这个错误是两个原因:一个是磁盘空间不足,还有一个是项目太大导致pdb文件太大,无法继续写入. 原本cocos2d- ...

  10. HTML5 画一张图

    笔者:本笃庆军 原文地址:http://blog.csdn.net/qingdujun/article/details/33344289 一.绘制图像 使用drawImage()方法绘制图像. 画图环 ...