本文转自:http://www.cnblogs.com/think8848/archive/2011/07/15/2107828.html

前些天写了一篇有关jqGrid的文章,因为是公司项目的原因一直没有提供源代码,今天又要用jqGrid,顺便做一个示例,以便有需要的人参考。源代码下载

为了使用方便起见,将jqGrid的一些选项放在了_Layout.cshtml中,这样就不用在每一个页面中重复输入了,见代码:

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/themes/base/site.css")" rel="Stylesheet" type="text/css" />
    <link href="@Url.Content("~/Content/themes/base/jquery.ui.css")" rel="Stylesheet" type="text/css" />
    <link href="@Url.Content("~/Content/themes/base/jquery.jqgrid.css")" rel="Stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.ui.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/i18n/grid.locale-cn.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.jqgrid.js")" type="text/javascript"></script>
    <script type="text/javascript">
        var gridContainerId = '#gridview', gridId = '#list';
        $(function () {
            $.extend($.jgrid.defaults, {
                ajaxGridOptions: { contentType: 'application/json; charset=utf-8' },
                datatype: 'json',
                mtype: 'GET',
                hidegrid: false,
                rownumbers: true,
                rowNum: 10,
                rowList: [10, 15, 20],
                sortorder: 'asc',
                viewrecords: true,
                pager: $('#pager'),
                height: 'auto',
                editfunc: function (id, data) { return false; },
                delfunc: function (id, data) { return false; },
                cleverjqgridactions: 'clever_jqgrid_actions',
                colActionsTitle: '操作'
            });
        });
        function cleverActions(cellvalue, options, rowObject) {
            return '<a href="javascript:void(0)" id="' + options.rowId + '" class="ui-corner-all clever-jqgrid-action clever-jqgrid-edit" style="float: left; margin-left: 5px; padding: 0px;" title="' + $.jgrid.nav.edittitle + '" onclick="actionClick(this,event)" onmouseover="actionMouseover(this,event)" onmouseout="actionMouseout(this,event)" ><span class="ui-icon ui-icon-pencil"></span></a>'
            + '<a href="javascript:void(0)" id="' + options.rowId + '" class="ui-corner-all clever-jqgrid-action clever-jqgrid-del" style="float: left; margin-left: 5px; padding: 0px;" title="' + $.jgrid.nav.deltitle + '" onclick="actionClick(this,event)" onmouseover="actionMouseover(this,event)" onmouseout="actionMouseout(this,event)" ><span class="ui-icon ui-icon-trash"></span></a>';
        }
        function actionMouseover(el, ev) {
            $(el).addClass('ui-state-hover');
            if ($.browser.msie) {
                ev.cancelBubble = true;
            } else {
                ev.stopPropagation();
            }
        }
        function actionMouseout(el, ev) {
            $(el).removeClass('ui-state-hover');
            if ($.browser.msie) {
                ev.cancelBubble = true;
            } else {
                ev.stopPropagation();
            }
        }
        function actionClick(el, ev) {
            var id = $(el).attr('id');
            var data = $(gridId).jqGrid('getRowData', id);
            if (data.clever_jqgrid_actions) {
                delete data.clever_jqgrid_actions;
            }
            if ($(el).hasClass('clever-jqgrid-edit')) {
                $(gridId).getGridParam('editfunc')(id, data);
            } else if ($(el).hasClass('clever-jqgrid-del')) {
                if (confirm($.jgrid.del.msg)) {
                    $(gridId).getGridParam('delfunc')(id, data);
                }
            }
            if ($.browser.msie) {
                ev.cancelBubble = true;
            } else {
                ev.stopPropagation();
            }
        }
    </script>
    @RenderSection("header", false)
    <script type="text/javascript">
        $(function () {
            $(window).bind('resize', function () {
                var width = $(gridContainerId).width();
                if (width == null || width < 1) {
                    width = $(gridContainerId).attr('offsetWidth');
                }
                width = width - 2;
                if (width > 0 && Math.abs(width - $(gridId).width()) > 5) {
                    $(gridId).setGridWidth(width);
                }
            }).trigger('resize');
        });   
    </script>
</head>
<body>
    @RenderBody()
</body>
</html>

为了使jqGrid能随着浏览器的缩放而自适应宽度,因此我在视图页面执行完javascript后又为jqGrid指定了resize事件。

在这里值的一提的是,要为jqGrid指定默认选项,需要使用$.jgrid.defaults,方法嘛当然是继承了,这里我把部分默认选项的说明给出来:

//指定请求数据时的ContentType,我使用了json

ajaxGridOptions: { contentType: 'application/json; charset=utf-8' },

//返回数据格式为json

datatype: 'json',

//Http方法为GET

mtype: 'GET',

//隐藏Grid的头

hidegrid: false,

//是否显示行号

rownumbers: true,

//默认显示数据行的个数

rowNum: 10,

//允许显示数据行个数的选项

rowList: [10, 15, 20],

//默认排序策略(升序)

sortorder: 'asc',

//是否显示表脚,即翻页所在的那行

viewrecords: true,

//页脚的容器

pager: $('#pager'),

//Grid高度自动调整

hieght: 'auto',

//这是我自定义的一个功能,后面会提到

editfunc: function (id, data) { return false; },

//自定义功能,同上

delfunc: function (id, data) { return false; },

//自定义功能,同上

cleverjqgridactions: 'clever_jqgrid_actions',

//自定义功能,同上

colActionsTitle: '操作'

一般情况下,在管理系统中,需要尽可能的减少用户的操作步骤,因此,把"编辑","删除"按钮直接放在数据行中,这样用户点一下就可以了,而不需要先选中一行,然后再去点击编辑/删除按钮,因此,使用自定义Formatter的方式,使每行增加一个"编辑","删除"按钮,方法如下:

在colModel中添加一个列:

{ name: $.jgrid.defaults.cleverjqgridactions, width: 80, fixed: true, sortable: false, resize: false, formatter: cleverActions }
上文中$.jgrid.defaults.cleverjqgridactions就是这个用途,为这个列提供一个不大可能重复的固定列定,以标示这个列,重点是formatter,为这个选项提供一个方法便是,这个方法的签名如下:
function (cellvalue, options, rowObject){
}
cellValue不用理会,因为它本来是指json为这个列提从的值,因为我们这个项不是json提供的,所以它肯定为undefined;
options里提供了这个列的定义(colModel中列的定义选项),该字段所在行的主键值(当然,得是你指定了某行为主键),以及jqGrid的id;
rowObject是一个数组,为截止目前,所在行的json数据,为啥是截止目前呢?因为当你这一列定义成功后,本列也成为行数据的一员了,在实际应用中,你肯定不希望这列的数据(其实就是你定义的按钮的HTML字符串)作为正式数据传入到业务逻辑里吧,所以使用delete方法要删除行数据中的这个字段值,那如何获取这个字段的名称呢?当..当..当,还记得$.jgrid.defaults.cleverjqgridactions吗?当然是使用它了(貌似是一个锉方法哦?)。
ok,知道了这些,我们来定义一个自定义的formatter:
function cleverActions(cellvalue, options, rowObject) {
    return '<a href="javascript:void(0)" id="' + options.rowId + '" class="ui-corner-all clever-jqgrid-action clever-jqgrid-edit" style="float: left; margin-left: 5px; padding: 0px;" title="' + $.jgrid.nav.edittitle + '" onclick="actionClick(this,event)" onmouseover="actionMouseover(this,event)" onmouseout="actionMouseout(this,event)" ><span class="ui-icon ui-icon-pencil"></span></a>'
    + '<a href="javascript:void(0)" id="' + options.rowId + '" class="ui-corner-all clever-jqgrid-action clever-jqgrid-del" style="float: left; margin-left: 5px; padding: 0px;" title="' + $.jgrid.nav.deltitle + '" onclick="actionClick(this,event)" onmouseover="actionMouseover(this,event)" onmouseout="actionMouseout(this,event)" ><span class="ui-icon ui-icon-trash"></span></a>';
}
使用$.jgrid.nav.edittitle和$.grid.nav.deltitle能获取到本地化的"编辑","删除"字符串,这样当用户把鼠标移动上按钮上时,就可以知道这两个按钮是什么用途了,所以将它哥俩的值指定给了a的title。
另外,我希望在我点击了"编辑"或是"删除"按钮时,就不要再触发行选中事件了,因此,我中止了事件冒泡,同样,我也中止了按钮的mouseover和mouseout事件冒泡:
function actionMouseover(el, ev) {
    $(el).addClass('ui-state-hover');
    if ($.browser.msie) {
        ev.cancelBubble = true;
    } else {
        ev.stopPropagation();
    }
}
function actionMouseout(el, ev) {
    $(el).removeClass('ui-state-hover');
    if ($.browser.msie) {
        ev.cancelBubble = true;
    } else {
        ev.stopPropagation();
    }
}
function actionClick(el, ev) {
    var id = $(el).attr('id');
    var data = $(gridId).jqGrid('getRowData', id);
    if (data.clever_jqgrid_actions) {
        delete data.clever_jqgrid_actions;
    }
    if ($(el).hasClass('clever-jqgrid-edit')) {
        $(gridId).getGridParam('editfunc')(id, data);
    } else if ($(el).hasClass('clever-jqgrid-del')) {
        if (confirm($.jgrid.del.msg)) {
            $(gridId).getGridParam('delfunc')(id, data);
        }
    }
    if ($.browser.msie) {
        ev.cancelBubble = true;
    } else {
        ev.stopPropagation();
    }
}
代码看到这里,我直是讨厌IE,就是整得和别人不一样。好好的就使用stopPropagation嘛,非得整啥cancelBubble呢?
var id = $(el).attr('id');
var data = $(gridId).jqGrid('getRowData', id);
鉴于在点击按钮后再获取行的主键值比较困难,我在生成铵钮时就将行主键值存在a标签的id中了,因此此时取出来,再使用getRowData方法获取该主键所在的行的数据对象,getRowData方法,据官方文档中说,性能不高,使用需谨慎,不要使用在for或是while中。
if (data.clever_jqgrid_actions) {
    delete data.clever_jqgrid_actions;
}
如果行数据包含了按钮HTML文本,则删除数据的这个属性
$(gridId).getGridParam('editfunc')(id, data);
使用getGridParam方法调用当点击了编辑按钮时的回调方法。
ok,至此,在_Layout.cshtml中的故事就讲完了,接下来我们来看看在实际使用的页面中是如何编码的:
@{
    ViewBag.Title = "Index";
}
@section header{
    <script type="text/javascript">
        $(function () {
            $('#list').jqGrid({
                url: '@Url.Action("Index", "User")',
                colNames: ['Primary Key', 'User Name', 'Email', $.jgrid.defaults.colActionsTitle],
                colModel: [
                { name: 'ID', index: 'ID', width: 1, hidden: true, key: true },
                { name: 'Name', index: 'Name', width: 100, align: 'left' },
                { name: 'Mail', index: 'Mail', width: 100, align: 'left' },
                { name: $.jgrid.defaults.cleverjqgridactions, width: 80, fixed: true, sortable: false, resize: false, formatter: cleverActions }
                ],
                sortname: 'Name',
                multiselect: true,
                editfunc: function (id, data) {
                    alert(id);
                },
                delfunc: function (id, data) {
                    alert(id);
                }
            });
        });
    </script>
}
<div id="gridview">
    <table id="list">
    </table>
    <div id="pager">
    </div>
</div>
有了_Layout.cshtml中的代码,这个页面上的代码就少多了,至少看起来不那么吓人了,照例来讲讲参数吧:
//地球人都知道,这是请求数据的url
url: '@Url.Action("Index", "User")',
//显示用的表头数据,$.jgrid.defaults.colActionsTitle本来的用途是显示"操作"两个字,但是不见得我在每个视图的资源文件中都定义吧,所以还是定义在_Layout.cshtml中,这样使用js的方式调用好可
colNames: ['Primary Key', 'User Name', 'Email', $.jgrid.defaults.colActionsTitle],
//定义数据列
colModel: [{ 
//列名
name: 'ID',
//排序时的键
index: 'ID',
//宽度,应该是px单位
width: 1, 
//隐藏
hidden: true,
//标示主键列
key: true },
                { name: 'Name', index: 'Name', width: 100, align: 'left' },
                { name: 'Mail', index: 'Mail', width: 100, align: 'left' },
                { name: $.jgrid.defaults.cleverjqgridactions, width: 80, fixed: true, sortable: false, resize: false, formatter: cleverActions }
                ],
//默认使用Name列排序
sortname: 'Name',
//是否允许多选,这个选项为true,则前面会加上一个全是checkbox的列,作用不用我多说了吧
multiselect: true,
//自定义formatter中编辑按钮的回调方法,id是本行的主键值,data是本行的所有数据
editfunc: function (id, data) {
                    alert(ids);
                },
//自定义formatter中删除按钮的回调方法
delfunc: function (id, data) {
                    alert(ids);
                }
有了这些差不多jqGrid就能很好的工作起来了,但是服务端的数据处理起来也够麻烦的,think8848一向作人厚道,因此专门写了两个助手类,专为jqGrid提供格式化的数据:
/// <summary>
/// 分页排序助手类
/// </summary>
public static class DataPagingHelper
{
    public static IQueryable<T> GetQueryable<T>(this IList<T> list, string sidx, string sord, int page, int rows)
    {
        return GetQueryable<T>(list.AsQueryable<T>(), sidx, sord, page, rows);
    }
 
    public static IQueryable<T> GetQueryable<T>(this IQueryable<T> queriable, string sidx, string sord, int page, int rows)
    {
        var data = ApplyOrder<T>(queriable, sidx, sord.ToLower() == "asc" ? true : false);
 
        return data.Skip<T>((page - 1) * rows).Take<T>(rows);
    }
 
    private static IOrderedQueryable<T> ApplyOrder<T>(IQueryable<T> queriable, string property, bool isASC)
    {
        PropertyInfo pi = typeof(T).GetProperty(property);
        ParameterExpression arg = Expression.Parameter(typeof(T), "x");
        Expression expr = Expression.Property(arg, pi);
 
        Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), pi.PropertyType);
        LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg);
 
        string methodName = isASC ? "OrderBy" : "OrderByDescending";
 
        object result = typeof(Queryable).GetMethods().Single(
                method => method.Name == methodName
                        && method.IsGenericMethodDefinition
                        && method.GetGenericArguments().Length == 2
                        && method.GetParameters().Length == 2)
                .MakeGenericMethod(typeof(T), pi.PropertyType)
                .Invoke(null, new object[] { queriable, lambda });
 
        return (IOrderedQueryable<T>)result;
    }
}
 
/// <summary>
/// jqGrid数据处理助手类
/// </summary>
public static class JqGridHelper
{
    public static JsonResult GetJson<T>(this IList<T> datas, string sidx, string sord, int page, int rows, JsonRequestBehavior behavior, params string[] fields)
    {
        return GetJson<T>(datas.AsQueryable<T>(), sidx, sord, page, rows, behavior, fields);
    }
 
    public static JsonResult GetJson<T>(this IQueryable<T> queriable, string sidx, string sord, int page, int rows, JsonRequestBehavior behavior, params string[] fields)
    {
        var data = queriable.GetQueryable<T>(sidx, sord, page, rows);
 
        var json = new JsonResult();
        json.JsonRequestBehavior = behavior;
 
        if (rows != 0)
        {
            var totalpages = (decimal)queriable.Count<T>() / (decimal)rows;
            totalpages = (totalpages == (int)totalpages) ? totalpages : (int)totalpages + 1;
 
            var rowsData = GetJsonData<T>(data, fields);
 
            json.Data = new
            {
                page,
                records = rows,
                total = (int)totalpages,
                rows = rowsData
            };
        }
 
        return json;
    }
 
    private static object[] GetJsonData<T>(IQueryable<T> queriable, params string[] fields)
    {
        var properties = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public);
 
        T[] datas = queriable.ToArray<T>();
 
        object[] result = new object[datas.Length];
 
        if (fields.Length == 0)
        {
            fields = Array.ConvertAll<PropertyInfo, string>(properties.Where<PropertyInfo>
                (x => x.GetCustomAttributes(typeof(InternalAttribute), false).Length == 0)
                .ToArray<PropertyInfo>()
                , delegate(PropertyInfo p)
                {
                    return p.Name;
                });
        }
 
        for (int i = 0; i < datas.Length; i++)
        {
            object[] values = new object[fields.Length];
            for (int j = 0; j < fields.Length; j++)
            {
                var pi = properties.First<PropertyInfo>(x => x.Name == fields[j]);
                var value = pi.GetValue(datas[i], null);
                values[j] = value != null ? value.ToString() : "";
            }
 
            result[i] = new { id = i, cell = values };
        }
 
        return result;
    }
}
 
/// <summary>
/// 本人项目中使用的,不用深究
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class InternalAttribute : Attribute { }
有了这两个助手类,我们再来看提供数据的服务是啥样的:
public class UserController : Controller
{
    //
    // GET: /User/
 
    public ActionResult Index(string sidx, string sord, int page, int rows)
    {
        var users = new List<User>();
        users.Add(new User() { ID = Guid.NewGuid(), Name = "think8848", Mail = "think8848@csdn.net", Password = "abcdefg" });
        users.Add(new User() { ID = Guid.NewGuid(), Name = "a", Mail = "a@csdn.net", Password = "abcdefg" });
        users.Add(new User() { ID = Guid.NewGuid(), Name = "b", Mail = "b@csdn.net", Password = "abcdefg" });
        //...
        users.Add(new User() { ID = Guid.NewGuid(), Name = "y", Mail = "y@csdn.net", Password = "abcdefg" });
        users.Add(new User() { ID = Guid.NewGuid(), Name = "z", Mail = "z@csdn.net", Password = "abcdefg" });
 
        return users.GetJson<User>(sidx, sord, page, rows, JsonRequestBehavior.AllowGet, new string[] { "ID", "Name", "Mail" });
    }
}
User实体定义:
public class User
{
    public Guid ID { get; set; }
    public string Name { get; set; }
    public string Password { get; set; }
    public string Mail { get; set; }
}
必须得完结了,我的脚被蚊子要抬走了...
效果图:

[转]ASP.NET MVC 3 Razor + jqGrid 示例的更多相关文章

  1. ASP.NET MVC:Razor 引入命名空间

    原文:ASP.NET MVC:Razor 引入命名空间 页面中引用 c# @using MvcApplication83.Models @using MvcApplication83.Common 行 ...

  2. ASP.NET MVC 自定义Razor视图WorkContext

    概述 1.在ASP.NET MVC项目开发的过程中,我们经常需要在cshtml的视图层输出一些公用信息 比如:页面Title.服务器日期时间.页面关键字.关键字描述.系统版本号.资源版本号等 2.普通 ...

  3. ASP.NET MVC (Razor)开发

    ASP.NET MVC (Razor)开发 过去我们使用过一些周报工具来完成项目组或部门的周报填写与考核工作,但多少有些不理想,要么功能太过简单,要么功能特别繁杂,不接地气,使用不便. 后来我们就考虑 ...

  4. ASP.NET MVC 3: Razor中的@:和语法

    原文 ASP.NET MVC 3: Razor中的@:和语法 [原文发表地址] ASP.NET MVC 3: Razor’s @: and <text> syntax[原文发表时间] De ...

  5. ASP.NET MVC (Razor)开发<<周报与绩效考核系统>>,并免费提供园友们使用~~~

    过去我们使用过一些周报工具来完成项目组或部门的周报填写与考核工作,但多少有些不理想,要么功能太过简单,要么功能特别繁杂,不接地气,使用不便. 后来我们就考虑自己开发一个简单的,实用的,易用的,接地气的 ...

  6. ASP.NET MVC Web API使用示例

    上篇博客讲解rest服务开发时,曾经提到过asp.net mvc中的rest api,由于篇幅原因,没有在上篇博客中进行讲解,这里专门拿出来进行讨论.还是一样引用上次的案例,用asp.net mvc提 ...

  7. ASP.NET MVC 3 Razor Views in SharePoint

    http://tqcblog.com/2011/01/22/asp-net-mvc-3-razor-views-in-sharepoint/ ASP.NET MVC 3 has just been r ...

  8. Asp.net mvc 5 razor

    一开始学习dotnet的web项目是Asp.net webform,完全不理解项目为什么要这样设计,就简单的使用ajax调用后台的代码不好吗?为什么还要搞一些什么代码后置的东东. 还有就是有各种加载问 ...

  9. Profession ASP.NET MVC 2.0 NerdDinner示例可运行源码

    最近一段时间在看JonGalloway等著作的<Profession ASP.NET MVC 2.0>.本书并没有按照常规的大部头书籍那样,按部就班的介绍MVC的概念等,而是在第一章直接引 ...

随机推荐

  1. B树详解

    B树 具体讲解之前,有一点,再次强调下:B-树,即为B树.因为B树的原英文名称为B-tree,而国内很多人喜欢把B-tree译作B-树,其实,这是个非常不好的直译,很容易让人产生误解.如人们可能会以为 ...

  2. 【我的产品观】开发wangEditor一年总结

    1. 引言 标题说是一周年,其实是不是正好是一周年,我也忘记了,光从github的提交记录看也不准确.印象中觉得,如果要论想法,到现在一年多了,如果要论实际写代码,可能差不多正好一年. 从8月底在济南 ...

  3. bootstrap源码分析之scrollspy(滚动侦听)

    源码文件: Scrollspy.js 实现功能 1.当滚动区域内设置的hashkey距离顶点到有效位置时,就关联设置其导航上的指定项2.导航必须是 .nav > li > a 结构,并且a ...

  4. bootstrapcss3触屏滑块轮播图

    插件描述:bootslider响应bootstrapcss3触屏滑块轮播图 小海已经好久没分享技术性文章了,这个基于bootstrap的触屏版轮播图绝对满足大家的胃口,并且支持移动端触摸滑动.功能上, ...

  5. css3中filter的各种特效

    css3中的filter属性可以说是简单易用且强大,这些效果作用在图片上实现一些特效(也可以作用在vidio上,此处只讨论图片特效). 浏览器兼容性 目前各大浏览器对于css3的兼容已经非常好了,最新 ...

  6. SharePoint 2013 – Workflow Manager 1.0 offline download

    [http://sharepointdeal.wordpress.com/2013/03/13/sharepoint-2013-workflow-manager-1-0-offline-downloa ...

  7. 【ios】使用Block对POST异步操作的简单封装

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/3409721.html 一般情况下的POST异步操作需要实现以下 ...

  8. 操作系统开发系列—13.a.进程 ●

    进程的切换及调度等内容是和保护模式的相关技术紧密相连的,这些代码量可能并不多,但却至关重要. 我们需要一个数据结构记录一个进程的状态,在进程要被挂起的时候,进程信息就被写入这个数据结构,等到进程重新启 ...

  9. 【转载】安卓APP架构

    注:本篇博文转载于 http://my.oschina.net/mengshuai/blog/541314?fromerr=z8tDxWUH 本文介绍了文章作者从事了几年android应用的开发,经历 ...

  10. redis使用笔记

    mysql---select * from table where xx;insert into table(name1,name2..) values(value1,value2);delete f ...