第一次看到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 -->
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
全部的layout.cshtml
<!DOCTYPE html>
<html >
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>@ViewBag.Title</title>
<link href="~/Content/CSS/bootstrap.min.css" rel="stylesheet" />
<link rel="stylesheet" href="~/Content/CSS/font-awesome.min.css" />
<script src="~/Content/Js/jquery-2.0.3.min.js"></script>
<link href="~/Content/CSS/niqiu.css" rel="stylesheet" />
<!--[if IE 7]>
<link rel="stylesheet" href="~/Content/CSS/font-awesome-ie7.min.css" />
<![endif]-->
<!-- page specific plugin styles -->
<!-- ace styles -->
<link rel="stylesheet" href="~/Content/CSS/ace.min.css" />
<link rel="stylesheet" href="~/Content/CSS/ace-rtl.min.css" />
<link rel="stylesheet" href="~/Content/CSS/ace-skins.min.css" />
<!--[if lte IE 8]>
<link rel="stylesheet" href="~/Content/CSS/ace-ie.min.css" />
<![endif]-->
<!-- inline styles related to this page -->
<!-- ace settings handler -->
<script src="~/Content/Js/ace-extra.min.js"></script>
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="~/Content/Js/html5shiv.js"></script>
<script src="~/Content/Js/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="navbar navbar-default" id="navbar">
<script type="text/javascript">
try { ace.settings.check('navbar', 'fixed') } catch (e) { }
</script>
<div class="navbar-container" id="navbar-container">
<div class="navbar-header pull-left">
<a href="#" class="navbar-brand">
<small>
<i class="icon-leaf"></i>
XiaoNao Admin
</small>
</a><!-- /.brand -->
</div><!-- /.navbar-header -->
<div class="navbar-header pull-right" role="navigation">
<ul class="nav ace-nav">
<li class="green">
<a data-toggle="dropdown" class="dropdown-toggle" href="#">
<i class="icon-envelope icon-animated-vertical"></i>
<span class="badge badge-success">5</span>
</a>
<ul class="pull-right dropdown-navbar dropdown-menu dropdown-caret dropdown-close">
<li class="dropdown-header">
<i class="icon-envelope-alt"></i>
Messages
</li>
<li>
<a href="#">
<img src="~/Content/avatars/avatar.png" class="msg-photo" alt="Alex's Avatar" />
<span class="msg-body">
<span class="msg-title">
<span class="blue">Alex:</span>
Ciao sociis natoque penatibus et auctor ...
</span>
<span class="msg-time">
<i class="icon-time"></i>
<span>a moment ago</span>
</span>
</span>
</a>
</li>
<li>
<a href="#">
<img src="~/Content/avatars/avatar3.png" class="msg-photo" alt="Susan's Avatar" />
<span class="msg-body">
<span class="msg-title">
<span class="blue">Susan:</span>
Vestibulum id ligula porta felis euismod ...
</span>
<span class="msg-time">
<i class="icon-time"></i>
<span>20 minutes ago</span>
</span>
</span>
</a>
</li>
<li>
<a href="#">
<img src="~/Content/avatars/avatar4.png" class="msg-photo" alt="Bob's Avatar" />
<span class="msg-body">
<span class="msg-title">
<span class="blue">Bob:</span>
Nullam quis risus eget urna mollis ornare ...
</span>
<span class="msg-time">
<i class="icon-time"></i>
<span>3:15 pm</span>
</span>
</span>
</a>
</li>
<li>
<a href="#">
See all messages
<i class="icon-arrow-right"></i>
</a>
</li>
</ul>
</li>
<li class="light-blue">
<a data-toggle="dropdown" href="#" class="dropdown-toggle">
<img class="nav-user-photo" src="~/Content/avatars/user.jpg" alt="Jason's Photo" />
<span class="user-info">
@if( Session["uname"]!=null){
<small>Welcome,</small>
@Session["uname"].ToString();
}
</span>
<i class="icon-caret-down"></i>
</a>
<ul class="user-menu pull-right dropdown-menu dropdown-yellow dropdown-caret dropdown-close">
<li>
<a href="#">
<i class="icon-cog"></i>
Settings
</a>
</li>
<li>
<a href="#">
<i class="icon-user"></i>
Profile
</a>
</li>
<li class="divider"></li>
<li>
<a href="@Url.Action("LogOff","User")">
<i class="icon-off"></i>
Logout
</a>
</li>
</ul>
</li>
</ul><!-- /.ace-nav -->
</div><!-- /.navbar-header -->
</div><!-- /.container -->
</div>
<div class="main-container" id="main-container">
<script type="text/javascript">
try { ace.settings.check('main-container', 'fixed') } catch (e) { }
</script>
<div class="main-container-inner">
<a class="menu-toggler" id="menu-toggler" href="#">
<span class="menu-text"></span>
</a>
<div class="sidebar" id="sidebar">
<script type="text/javascript">
try { ace.settings.check('sidebar', 'fixed') } catch (e) { }
</script>
<div class="sidebar-shortcuts" id="sidebar-shortcuts">
<div class="sidebar-shortcuts-large" id="sidebar-shortcuts-large">
<button class="btn btn-success">
<i class="icon-signal"></i>
</button>
<button class="btn btn-info">
<i class="icon-pencil"></i>
</button>
<button class="btn btn-warning">
<i class="icon-group"></i>
</button>
<button class="btn btn-danger">
<i class="icon-cogs"></i>
</button>
</div>
<div class="sidebar-shortcuts-mini" id="sidebar-shortcuts-mini">
<span class="btn btn-success"></span>
<span class="btn btn-info"></span>
<span class="btn btn-warning"></span>
<span class="btn btn-danger"></span>
</div>
</div>
<!-- #sidebar-shortcuts -->
<ul class="nav nav-list">
<li class="active">
<a href="@Url.Action("Index","Admin")">
<i class="icon-dashboard"></i>
<span class="menu-text"> 控制台 </span>
</a>
</li>
<li>
<a href="#" class="dropdown-toggle">
<i class="icon-list"></i>
<span class="menu-text"> 产品 </span>
<b class="arrow icon-angle-down"></b>
</a>
<ul class="submenu">
<li>
<a href="@Url.Action("Index","Product")">
<i class="icon-double-angle-right"></i>
产品管理
</a>
</li>
<li>
<a href="@Url.Action("CategoryList","Product")">
<i class="icon-double-angle-right"></i>
分类管理
</a>
</li>
</ul>
</li>
<li>
<a href="#" class="dropdown-toggle">
<i class="icon-desktop"></i>
<span class="menu-text"> 用户 </span>
<b class="arrow icon-angle-down"></b>
</a>
<ul class="submenu">
<li>
<a href="@Url.Action("Index","User")">
<i class="icon-double-angle-right"></i>
用户管理
</a>
</li>
<li>
<a href="@Url.Action("EditInfo","User")">
<i class="icon-double-angle-right"></i>
个人设置
</a>
</li>
</ul>
</li>
</ul><!-- /.nav-list -->
<div class="sidebar-collapse" id="sidebar-collapse">
<i class="icon-double-angle-left" data-icon1="icon-double-angle-left" data-icon2="icon-double-angle-right"></i>
</div>
<script type="text/javascript">
try { ace.settings.check('sidebar', 'collapsed') } catch (e) { }
</script>
</div>
<div class="main-content">
<div class="breadcrumbs" id="breadcrumbs">
<script type="text/javascript">
try { ace.settings.check('breadcrumbs', 'fixed') } catch (e) { }
</script>
<ul class="breadcrumb">
<li>
<i class="icon-home home-icon"></i>
<a href="@Url.Action("Index","Admin")">Home</a>
</li>
<li id="currentpart" class="active">控制台</li>
</ul><!-- .breadcrumb -->
<div class="nav-search" id="nav-search">
<form class="form-search">
<span class="input-icon">
<input type="text" placeholder="Search ..." class="nav-search-input" id="nav-search-input" autocomplete="off" />
<i class="icon-search nav-search-icon"></i>
</span>
</form>
</div><!-- #nav-search -->
</div>
<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 -->
</div><!-- /.main-content -->
<div class="ace-settings-container" id="ace-settings-container">
<div class="btn btn-app btn-xs btn-warning ace-settings-btn" id="ace-settings-btn">
<i class="icon-cog bigger-150"></i>
</div>
<div class="ace-settings-box" id="ace-settings-box">
<div>
<div class="pull-left">
<select id="skin-colorpicker" class="hide">
<option data-skin="default" value="#438EB9">#438EB9</option>
<option data-skin="skin-1" value="#222A2D">#222A2D</option>
<option data-skin="skin-2" value="#C6487E">#C6487E</option>
<option data-skin="skin-3" value="#D0D0D0">#D0D0D0</option>
</select>
</div>
<span> Choose Skin</span>
</div>
<div>
<input type="checkbox" class="ace ace-checkbox-2" id="ace-settings-navbar" />
<label class="lbl" for="ace-settings-navbar"> Fixed Navbar</label>
</div>
<div>
<input type="checkbox" class="ace ace-checkbox-2" id="ace-settings-sidebar" />
<label class="lbl" for="ace-settings-sidebar"> Fixed Sidebar</label>
</div>
<div>
<input type="checkbox" class="ace ace-checkbox-2" id="ace-settings-breadcrumbs" />
<label class="lbl" for="ace-settings-breadcrumbs"> Fixed Breadcrumbs</label>
</div>
<div>
<input type="checkbox" class="ace ace-checkbox-2" id="ace-settings-rtl" />
<label class="lbl" for="ace-settings-rtl"> Right To Left (rtl)</label>
</div>
<div>
<input type="checkbox" class="ace ace-checkbox-2" id="ace-settings-add-container" />
<label class="lbl" for="ace-settings-add-container">
Inside
<b>.container</b>
</label>
</div>
</div>
</div><!-- /#ace-settings-container -->
</div><!-- /.main-container-inner -->
<a href="#" id="btn-scroll-up" class="btn-scroll-up btn btn-sm btn-inverse">
<i class="icon-double-angle-up icon-only bigger-110"></i>
</a>
</div><!-- /.main-container -->
<!-- basic scripts -->
<!--[if !IE]>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<![endif]-->
<!--[if IE]>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<![endif]-->
<!--[if IE]>
<script type="text/javascript">
window.jQuery || document.write("<script src='~/Content/Js/jquery-1.10.2.min.js'>"+"<"+"/script>");
</script>
<![endif]-->
<script type="text/javascript">
if ("ontouchend" in document) document.write("<script src='~/Content/Js/jquery.mobile.custom.min.js'>" + "<" + "/script>");
</script>
<script src="~/Content/Js/bootstrap.min.js"></script>
<script src="~/Content/Js/typeahead-bs2.min.js"></script>
<!-- page specific plugin scripts -->
<script src="~/Content/Js/jquery-ui-1.10.3.custom.min.js"></script>
<script src="~/Content/Js/jquery.ui.touch-punch.min.js"></script>
<script src="~/Content/Js/bootbox.min.js"></script>
<!-- ace scripts -->
<script src="~/Content/Js/ace-elements.min.js"></script>
<script src="~/Content/Js/ace.min.js"></script>
<!-- inline scripts related to this page -->
<script type="text/javascript">
jQuery(function ($) {
/* initialize the external events
-----------------------------------------------------------------*/
$('#external-events div.external-event').each(function () {
// create an Event Object (http://arshaw.com/fullcalendar/docs/event_data/Event_Object/)
// it doesn't need to have a start or end
var eventObject = {
title: $.trim($(this).text()) // use the element's text as the event title
};
// store the Event Object in the DOM element so we can get to it later
$(this).data('eventObject', eventObject);
// make the event draggable using jQuery UI
$(this).draggable({
zIndex: 999,
revert: true, // will cause the event to go back to its
revertDuration: 0 // original position after the drag
});
});
/* initialize the calendar
-----------------------------------------------------------------*/
})
</script>
<div style="display:none"><script src='http://v7.cnzz.com/stat.php?id=155540&web_id=155540' language='JavaScript' charset='gb2312'></script></div>
<script src="~/Content/Js/niqiu.js"></script>
@RenderSection("scripts", required: false)
</body></html>
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
- 134.
- 135.
- 136.
- 137.
- 138.
- 139.
- 140.
- 141.
- 142.
- 143.
- 144.
- 145.
- 146.
- 147.
- 148.
- 149.
- 150.
- 151.
- 152.
- 153.
- 154.
- 155.
- 156.
- 157.
- 158.
- 159.
- 160.
- 161.
- 162.
- 163.
- 164.
- 165.
- 166.
- 167.
- 168.
- 169.
- 170.
- 171.
- 172.
- 173.
- 174.
- 175.
- 176.
- 177.
- 178.
- 179.
- 180.
- 181.
- 182.
- 183.
- 184.
- 185.
- 186.
- 187.
- 188.
- 189.
- 190.
- 191.
- 192.
- 193.
- 194.
- 195.
- 196.
- 197.
- 198.
- 199.
- 200.
- 201.
- 202.
- 203.
- 204.
- 205.
- 206.
- 207.
- 208.
- 209.
- 210.
- 211.
- 212.
- 213.
- 214.
- 215.
- 216.
- 217.
- 218.
- 219.
- 220.
- 221.
- 222.
- 223.
- 224.
- 225.
- 226.
- 227.
- 228.
- 229.
- 230.
- 231.
- 232.
- 233.
- 234.
- 235.
- 236.
- 237.
- 238.
- 239.
- 240.
- 241.
- 242.
- 243.
- 244.
- 245.
- 246.
- 247.
- 248.
- 249.
- 250.
- 251.
- 252.
- 253.
- 254.
- 255.
- 256.
- 257.
- 258.
- 259.
- 260.
- 261.
- 262.
- 263.
- 264.
- 265.
- 266.
- 267.
- 268.
- 269.
- 270.
- 271.
- 272.
- 273.
- 274.
- 275.
- 276.
- 277.
- 278.
- 279.
- 280.
- 281.
- 282.
- 283.
- 284.
- 285.
- 286.
- 287.
- 288.
- 289.
- 290.
- 291.
- 292.
- 293.
- 294.
- 295.
- 296.
- 297.
- 298.
- 299.
- 300.
- 301.
- 302.
- 303.
- 304.
- 305.
- 306.
- 307.
- 308.
- 309.
- 310.
- 311.
- 312.
- 313.
- 314.
- 315.
- 316.
- 317.
- 318.
- 319.
- 320.
- 321.
- 322.
- 323.
- 324.
- 325.
- 326.
- 327.
- 328.
- 329.
- 330.
- 331.
- 332.
- 333.
- 334.
- 335.
- 336.
- 337.
- 338.
- 339.
- 340.
- 341.
- 342.
- 343.
- 344.
- 345.
- 346.
- 347.
- 348.
- 349.
- 350.
- 351.
- 352.
- 353.
- 354.
- 355.
- 356.
- 357.
- 358.
- 359.
- 360.
- 361.
- 362.
- 363.
- 364.
- 365.
- 366.
- 367.
- 368.
- 369.
- 370.
- 371.
- 372.
- 373.
- 374.
- 375.
- 376.
- 377.
- 378.
- 379.
- 380.
- 381.
- 382.
- 383.
- 384.
- 385.
- 386.
- 387.
- 388.
- 389.
- 390.
- 391.
- 392.
- 393.
- 394.
- 395.
- 396.
- 397.
- 398.
- 399.
- 400.
- 401.
- 402.
- 403.
- 404.
- 405.
- 406.
- 407.
- 408.
- 409.
- 410.
- 411.
- 412.
- 413.
- 414.
- 415.
- 416.
- 417.
- 418.
- 419.
- 420.
- 421.
- 422.
- 423.
- 424.
- 425.
- 426.
- 427.
- 428.
- 429.
- 430.
- 431.
- 432.
- 433.
- 434.
- 435.
- 436.
- 437.
- 438.
- 439.
- 440.
- 441.
- 442.
- 443.
- 444.
- 445.
- 446.
- 447.
- 448.
- 449.
- 450.
- 451.
- 452.
- 453.
- 454.
- 455.
- 456.
- 457.
- 458.
- 459.
#p#
二、引入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>
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
list用来呈现数据,pager用来分页,errorinfo用来提示错误。jqgrid,涉及的配置比较多。需要后台代码的全面的支持,所以在介绍配置之前,先介绍下模型和仓库。
1.Product: 我们需要呈现的一个是一个产品,有很多不同的价格及其他,这些都将成为表格的列名。
public class Product
{
/// <summary>
/// Gets or sets the id.
/// </summary>
/// <value>The id.</value>
[Key]
public int ProductId { get; set; }
/// <summary>
/// 直接做型号处理
/// </summary>
public string ProductName { get; set; }
/// <summary>
/// Gets or sets the category.
/// </summary>
/// <value>The category.</value>
public string Category { get; set; }
/// <summary>
/// Gets or sets the brand.
/// </summary>
/// <value>The brand.</value>
public string Brand { get; set; }
public string Size { get; set; }
/// <summary>
/// Gets or sets the 规格.
/// </summary>
/// <value>The standard.</value>
public string Standard { get; set; }
/// <summary>
/// 专柜
/// </summary>
public decimal ZhuanGui { get; set; }
/// <summary>
/// Gets or sets the 莎莎 price.
/// </summary>
/// <value>The sa sa price.</value>
public decimal SaSaPrice { get; set; }
/// <summary>
/// Gets or sets the 卓越 price.
/// </summary>
/// <value>The zhuoyue price.</value>
public decimal ZhuoyuePrice { get; set; }
/// <summary>
/// Gets or sets the 卡莱美 price.
/// </summary>
/// <value>The ka lai price.</value>
public decimal KaLaiPrice { get; set; }
/// <summary>
/// 雅施
/// </summary>
public decimal YaShi { get; set; }
/// <summary>
/// Gets or sets the 万宁 price.
/// </summary>
/// <value>The wanning price.</value>
public decimal WanningPrice { get; set; }
/// <summary>
/// Gets or sets the 屈臣氏 price.
/// </summary>
/// <value>The quchengshi price.</value>
public decimal QuchengshiPrice { get; set; }
/// <summary>
/// Gets or sets the 药店 price.
/// </summary>
/// <value>The drugstore price.</value>
public decimal DrugstorePrice { get; set; }
/// <summary>
/// Gets or sets the others.
/// </summary>
/// <value>The others.</value>
public string Others { get; set; }
/// <summary>
/// Gets or sets the create time.
/// </summary>
/// <value>The create time.</value>
public DateTime CreateTime { get; set; }
public string ImgUrl { get; set; }
public Product()
{
CreateTime = DateTime.Now;
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
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;
}
//....
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
在只考虑排序的情况下,控制器的代码就相对简单:
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);
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
如果涉及到复杂些的查询,等于不等于,包含之类的,会多了后面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);
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
需要说明的是,这里的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;
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
2)需要一个新增:(记住返回json的时候要allowGet,不然可能造成添加失败,其他地方同理)
[HttpPost]
public ActionResult Create(Product product)
{
_repository.Add(product);
var fu = _repository.FindByName(product.ProductName);
return Json(fu, JsonRequestBehavior.AllowGet);
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
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); ;
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
有了这四个方法就ok了。下面来讲配置。先打个预防针,主要关心两个方法,一个设置table,一个设置分页。然后代码比较长..... 希望没有打消你驾驭它的渴望。
全部控制器代码:包含了分类的一些,道理一样
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Web;
using System.Web.Mvc;
using XNManage.Common;
using XNManage.Models;
using XNManage.Repository;
using XNManage.ViewModel;
namespace XNManage.Controllers
{
public class ProductController : Controller
{
//
// GET: /Product/
private readonly IProductRepository _repository;
private IEnumerable<CategoryViewModel> _categoryViewModels = new List<CategoryViewModel>();
public ProductController(IProductRepository repository)
{
_repository = repository;
}
#region 产品
[LoginValid]
public ActionResult Index()
{
//CategoryInit();
//ProductsInits();
return View();
}
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);
}
private IEnumerable<Product> GetRawPros(bool search = false, string searchField = "", string searchOper = "", string searchString = "")
{
var rawpros = _repository.FindAll();
if (!search) return rawpros;
switch (switchSidx(searchField))
{
case "ProductName":
switch (searchOper)
{
case "cn":
rawpros = rawpros.Where(n => n.ProductName.Contains(searchString));
break;
case "eq":
rawpros = rawpros.Where(n => n.ProductName == searchString);
break;
case "ne":
rawpros = rawpros.Where(n => n.ProductName != searchString);
break;
default:
rawpros = rawpros.Where(n => n.ProductName.Contains(searchString));
break;
}
break;
case "Category":
switch (searchOper)
{
case "cn":
rawpros = rawpros.Where(n => n.Category.Contains(searchString));
break;
case "eq":
rawpros = rawpros.Where(n => n.Category == searchString);
break;
case "ne":
rawpros = rawpros.Where(n => n.Category != searchString);
break;
default:
rawpros = rawpros.Where(n => n.Category.Contains(searchString));
break;
}
break;
case "Brand":
switch (searchOper)
{
case "cn":
rawpros = rawpros.Where(n => n.Brand.Contains(searchString));
break;
case "eq":
rawpros = rawpros.Where(n => n.Brand == searchString);
break;
case "ne":
rawpros = rawpros.Where(n => n.Brand != searchString);
break;
default:
rawpros = rawpros.Where(n => n.Brand.Contains(searchString));
break;
}
break;
case "SaSaPrice":
switch (searchOper)
{
case "cn":
rawpros = rawpros.Where(n => n.SaSaPrice >= Convert.ToDecimal(searchString));
break;
case "eq":
rawpros = rawpros.Where(n => n.SaSaPrice == Convert.ToDecimal(searchString));
break;
case "ne":
rawpros = rawpros.Where(n => n.SaSaPrice != Convert.ToDecimal(searchString));
break;
}
break;
case "ZhuanGui":
switch (searchOper)
{
case "cn":
rawpros = rawpros.Where(n => n.ZhuanGui >= Convert.ToDecimal(searchString));
break;
case "eq":
rawpros = rawpros.Where(n => n.ZhuanGui == Convert.ToDecimal(searchString));
break;
case "ne":
rawpros = rawpros.Where(n => n.ZhuanGui != Convert.ToDecimal(searchString));
break;
}
break;
case "YaShi":
switch (searchOper)
{
case "cn":
rawpros = rawpros.Where(n => n.YaShi >= Convert.ToDecimal(searchString));
break;
case "eq":
rawpros = rawpros.Where(n => n.YaShi == Convert.ToDecimal(searchString));
break;
case "ne":
rawpros = rawpros.Where(n => n.YaShi != Convert.ToDecimal(searchString));
break;
}
break;
case "ZhuoyuePrice":
switch (searchOper)
{
case "cn":
rawpros = rawpros.Where(n => n.ZhuoyuePrice >= Convert.ToDecimal(searchString));
break;
case "eq":
rawpros = rawpros.Where(n => n.ZhuoyuePrice == Convert.ToDecimal(searchString));
break;
case "ne":
rawpros = rawpros.Where(n => n.ZhuoyuePrice != Convert.ToDecimal(searchString));
break;
}
break;
case "WanningPrice":
switch (searchOper)
{
case "cn":
rawpros = rawpros.Where(n => n.WanningPrice >= Convert.ToDecimal(searchString));
break;
case "eq":
rawpros = rawpros.Where(n => n.WanningPrice == Convert.ToDecimal(searchString));
break;
case "ne":
rawpros = rawpros.Where(n => n.WanningPrice != Convert.ToDecimal(searchString));
break;
}
break;
case "QuchengshiPrice":
switch (searchOper)
{
case "cn":
rawpros = rawpros.Where(n => n.QuchengshiPrice >= Convert.ToDecimal(searchString));
break;
case "eq":
rawpros = rawpros.Where(n => n.QuchengshiPrice == Convert.ToDecimal(searchString));
break;
case "ne":
rawpros = rawpros.Where(n => n.QuchengshiPrice != Convert.ToDecimal(searchString));
break;
}
break;
case "DrugstorePrice":
switch (searchOper)
{
case "cn":
rawpros = rawpros.Where(n => n.DrugstorePrice >= Convert.ToDecimal(searchString));
break;
case "eq":
rawpros = rawpros.Where(n => n.DrugstorePrice == Convert.ToDecimal(searchString));
break;
case "ne":
rawpros = rawpros.Where(n => n.DrugstorePrice != Convert.ToDecimal(searchString));
break;
}
break;
case "Others":
switch (searchOper)
{
case "cn":
rawpros = rawpros.Where(n => n.Others.Contains(searchString));
break;
case "eq":
rawpros = rawpros.Where(n => n.Others ==searchString);
break;
case "ne":
rawpros = rawpros.Where(n => n.Others !=searchString);
break;
}
break;
case "KaLaiPrice":
switch (searchOper)
{
case "cn":
rawpros = rawpros.Where(n => n.KaLaiPrice >= Convert.ToDecimal(searchString));
break;
case "eq":
rawpros = rawpros.Where(n => n.KaLaiPrice == Convert.ToDecimal(searchString));
break;
case "ne":
rawpros = rawpros.Where(n => n.KaLaiPrice != Convert.ToDecimal(searchString));
break;
}
break;
default:
break;
}
return rawpros;
}
/*
public JsonResult GetData(GridSettings grid)
{
var query = _repository.FindAll();
//filtring
if (grid.IsSearch)
{
//And
if (grid.Where.groupOp == "AND")
foreach (var rule in grid.Where.rules)
query = query.Where<Product>(
rule.field, rule.data,
(WhereOperation)StringEnum.Parse(typeof(WhereOperation), rule.op));
else
{
//Or
var temp = (new List<Product>()).AsQueryable();
foreach (var rule in grid.Where.rules)
{
var t = query.Where<Product>(
rule.field, rule.data,
(WhereOperation)StringEnum.Parse(typeof(WhereOperation), rule.op));
temp = temp.Concat<Product>(t);
}
//remove repeating records
query = temp.Distinct<Product>();
}
}
//sorting
query = query.OrderBy<Product>(grid.SortColumn,
grid.SortOrder);
//count
var count = query.Count();
//paging
var data = query.Skip((grid.PageIndex - 1) * grid.PageSize).Take(grid.PageSize).ToArray();
//converting in grid format
var result = new
{
total = (int)Math.Ceiling((double)count / grid.PageSize),
page = grid.PageIndex,
records = count,
rows = data.ToArray()
};
//convert to JSON and return to client
return Json(result, JsonRequestBehavior.AllowGet);
}
*/
//这个函数其实不必要!index中可以写英文。列名和index没有关系
private string switchSidx(string sidx)
{
switch (sidx)
{
case "型号":
return "ProductName";
case "类别":
return "Category";
case "品牌":
return "Brand";
case "规格":
return "Standard";
case "专柜":
return "ZhuanGui";
case "莎莎":
return "SaSaPrice";
case "雅施":
return "YaShi";
case "卓越":
return "ZhuoyuePrice";
case "卡莱美":
return "KaLaiPrice";
case "万宁":
return "WanningPrice";
case "屈臣氏":
return "QuchengshiPrice";
case "药店":
return "DrugstorePrice";
case "其他":
return "Others";
case "描述":
return "Description";
case "更新时间":
return "CreateTime";
default:
return "ProductName";
}
}
public string CategorySelectList()
{
var cs = _repository.AllCategories();
var sb=new StringBuilder("<select>");
foreach (var category in cs)
{
sb.Append(string.Format("<option value='{0}' >{1}</option>", category.CategoryName, category.CategoryName));
}
sb.Append("</select>");
return sb.ToString();
}
[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);
}
//
// POST: /Product/Create
[HttpPost]
public ActionResult Create(Product product)
{
_repository.Add(product);
var fu = _repository.FindByName(product.ProductName);
return Json(fu, JsonRequestBehavior.AllowGet);
}
//
// POST: /Product/Delete/5
[HttpPost]
public ActionResult Delete(int id)
{
_repository.Remove(id);
return Json(id);
}
private void CategoryInit()
{
if (!_repository.AllCategories().Any())
{
_repository.AddCategorie(new Category
{
CategoryName = "护肤品",
Description = "春天女生护肤专用"
});
_repository.AddCategorie(new Category()
{
CategoryName = "防晒",
Description = "夏日喷雾防晒"
}
);
}
}
private void ProductsInits()
{
if (!_repository.FindAll().Any())
{
_repository.Add(new Product()
{
ProductName = "水宝宝",
Others = "防晒",
SaSaPrice = 78,
DrugstorePrice = 98
});
}
}
#endregion
#region 分类
private IEnumerable<CategoryViewModel> initCategoryViewModels()
{
if (!_categoryViewModels.Any())
{
var cas = _repository.AllCategories();
_categoryViewModels = cas.Select(n => new CategoryViewModel()
{
CategoryId = n.CategoryId,
CategoryName = n.CategoryName,
Description = n.Description,
ProductCount = _repository.GetCategorieProducts(n.CategoryName).Count()
});
}
return _categoryViewModels;
}
public JsonResult GetAllCategorys(string sord = "asc", string sidx = "CategoryName", int page = 1, int rows = 10)
{
IList<object> pros = new List<object>(FindCategoryViewModels(sord, sidx, (page - 1) * rows, rows));
var jsonData = JqGridModel.GridData(page, rows, initCategoryViewModels().Count(), pros);
return Json(jsonData, JsonRequestBehavior.AllowGet);
}
public IEnumerable<CategoryViewModel> FindCategoryViewModels(string sort = "asc",
string property = "CategoryName", int skip = 0, int take = 10)
{
var propertyInfo = typeof(CategoryViewModel).GetProperty(property);
Func<CategoryViewModel, object> expn = e => propertyInfo.GetValue(e, null);
var fakeProfiles =initCategoryViewModels();
IEnumerable<CategoryViewModel> pros = sort == "asc" ? fakeProfiles.OrderBy(expn).Skip(skip).Take(take).ToArray()
: fakeProfiles.OrderByDescending(expn).Skip(skip).Take(take).ToArray();
return pros;
}
public ActionResult EditCategory(CategoryViewModel model,string oper, int id)
{
if (oper == "edit")
{
var ca = new Category()
{
CategoryId = model.CategoryId,
CategoryName = model.CategoryName,
Description = model.Description,
};
_repository.UpdateCategorie(ca);
}
return Json(model, JsonRequestBehavior.AllowGet);
}
public ActionResult CategoryList()
{
return View();
}
[HttpPost]
public ActionResult CreateCategory(Category category)
{
_repository.AddCategorie(category);
var fu = _repository.FindCategorieById(category.CategoryId);
var cm = new CategoryViewModel()
{
CategoryName = fu.CategoryName,
CategoryId = fu.CategoryId,
Description = fu.Description,
ProductCount = _repository.GetCategorieProducts(fu.CategoryName).Count()
};
return Json(cm, JsonRequestBehavior.AllowGet);
}
public ActionResult DeletCategory(int id)
{
_repository.RemoveCategorie(id);
return Json(1);
}
public PartialViewResult JqgridInit()
{
return PartialView();
}
public JsonResult GetChartData()
{
var cms = initCategoryViewModels().ToList();
var count =_repository.Count;
var chartDatas = cms.Select(n => new ChartData
{
label = n.CategoryName,
data = Math.Round((double)n.ProductCount / count, 3),
}).ToArray();
return Json(chartDatas, JsonRequestBehavior.AllowGet);
}
#endregion
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
- 134.
- 135.
- 136.
- 137.
- 138.
- 139.
- 140.
- 141.
- 142.
- 143.
- 144.
- 145.
- 146.
- 147.
- 148.
- 149.
- 150.
- 151.
- 152.
- 153.
- 154.
- 155.
- 156.
- 157.
- 158.
- 159.
- 160.
- 161.
- 162.
- 163.
- 164.
- 165.
- 166.
- 167.
- 168.
- 169.
- 170.
- 171.
- 172.
- 173.
- 174.
- 175.
- 176.
- 177.
- 178.
- 179.
- 180.
- 181.
- 182.
- 183.
- 184.
- 185.
- 186.
- 187.
- 188.
- 189.
- 190.
- 191.
- 192.
- 193.
- 194.
- 195.
- 196.
- 197.
- 198.
- 199.
- 200.
- 201.
- 202.
- 203.
- 204.
- 205.
- 206.
- 207.
- 208.
- 209.
- 210.
- 211.
- 212.
- 213.
- 214.
- 215.
- 216.
- 217.
- 218.
- 219.
- 220.
- 221.
- 222.
- 223.
- 224.
- 225.
- 226.
- 227.
- 228.
- 229.
- 230.
- 231.
- 232.
- 233.
- 234.
- 235.
- 236.
- 237.
- 238.
- 239.
- 240.
- 241.
- 242.
- 243.
- 244.
- 245.
- 246.
- 247.
- 248.
- 249.
- 250.
- 251.
- 252.
- 253.
- 254.
- 255.
- 256.
- 257.
- 258.
- 259.
- 260.
- 261.
- 262.
- 263.
- 264.
- 265.
- 266.
- 267.
- 268.
- 269.
- 270.
- 271.
- 272.
- 273.
- 274.
- 275.
- 276.
- 277.
- 278.
- 279.
- 280.
- 281.
- 282.
- 283.
- 284.
- 285.
- 286.
- 287.
- 288.
- 289.
- 290.
- 291.
- 292.
- 293.
- 294.
- 295.
- 296.
- 297.
- 298.
- 299.
- 300.
- 301.
- 302.
- 303.
- 304.
- 305.
- 306.
- 307.
- 308.
- 309.
- 310.
- 311.
- 312.
- 313.
- 314.
- 315.
- 316.
- 317.
- 318.
- 319.
- 320.
- 321.
- 322.
- 323.
- 324.
- 325.
- 326.
- 327.
- 328.
- 329.
- 330.
- 331.
- 332.
- 333.
- 334.
- 335.
- 336.
- 337.
- 338.
- 339.
- 340.
- 341.
- 342.
- 343.
- 344.
- 345.
- 346.
- 347.
- 348.
- 349.
- 350.
- 351.
- 352.
- 353.
- 354.
- 355.
- 356.
- 357.
- 358.
- 359.
- 360.
- 361.
- 362.
- 363.
- 364.
- 365.
- 366.
- 367.
- 368.
- 369.
- 370.
- 371.
- 372.
- 373.
- 374.
- 375.
- 376.
- 377.
- 378.
- 379.
- 380.
- 381.
- 382.
- 383.
- 384.
- 385.
- 386.
- 387.
- 388.
- 389.
- 390.
- 391.
- 392.
- 393.
- 394.
- 395.
- 396.
- 397.
- 398.
- 399.
- 400.
- 401.
- 402.
- 403.
- 404.
- 405.
- 406.
- 407.
- 408.
- 409.
- 410.
- 411.
- 412.
- 413.
- 414.
- 415.
- 416.
- 417.
- 418.
- 419.
- 420.
- 421.
- 422.
- 423.
- 424.
- 425.
- 426.
- 427.
- 428.
- 429.
- 430.
- 431.
- 432.
- 433.
- 434.
- 435.
- 436.
- 437.
- 438.
- 439.
- 440.
- 441.
- 442.
- 443.
- 444.
- 445.
- 446.
- 447.
- 448.
- 449.
- 450.
- 451.
- 452.
- 453.
- 454.
- 455.
- 456.
- 457.
- 458.
- 459.
- 460.
- 461.
- 462.
- 463.
- 464.
- 465.
- 466.
- 467.
- 468.
- 469.
- 470.
- 471.
- 472.
- 473.
- 474.
- 475.
- 476.
- 477.
- 478.
- 479.
- 480.
- 481.
- 482.
- 483.
- 484.
- 485.
- 486.
- 487.
- 488.
- 489.
- 490.
- 491.
- 492.
- 493.
- 494.
- 495.
- 496.
- 497.
- 498.
- 499.
- 500.
- 501.
- 502.
- 503.
- 504.
- 505.
- 506.
- 507.
- 508.
- 509.
- 510.
- 511.
- 512.
- 513.
- 514.
- 515.
- 516.
- 517.
- 518.
- 519.
- 520.
- 521.
- 522.
- 523.
- 524.
- 525.
- 526.
- 527.
- 528.
#p#
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
});
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
形成样子如下:
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
}
);
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
在下面加入按钮的方法以及执行删除: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);
}
});
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
形成这个样子:
全部前台代码:
@{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
@Html.Partial("JqgridInit")
<script>
$(function () {
$(".page-header h1 span,#currentpart").html("产品");
$(".page-header h1 small span").html("产品管理");
$(".nav-list>li:eq(1)").addClass("active").siblings().removeClass("active");
jQuery("#list2").jqGrid({
url: '/Product/GetAllPros',
datatype: "json",
colNames: ['操作', 'ProductId', '类别', '品牌', '型号', '规格', '专柜', '莎莎', '卓越', '卡莱美', '雅施', '万宁', '屈臣氏', '药店', '其他', '更新时间'],
colModel: [
{
name: 'myac', index: '操作', width: 60, fixed: true, sortable: false, resize: false, formatter: 'actions', formatoptions: {
keys: true,
delOptions: { recreateForm: true, beforeShowForm: beforeDeleteCallback, },//改变原来的样式 msg: '您确定要删除这条记录?</span>
searchoptions: { sopt: ['eq', 'ne', 'cn'] },
}
// name: 'act', index: 'act', width: 75, sortable: false
},
{ 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();
//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",
//无效!!!!
serializeDelData: function (postdata) {
var rowdata = jQuery('#list2').getRowData(postdata.id);
return { id: postdata.id, oper: postdata.oper, user: rowdata };
}
//edit del
});
jQuery("#list2").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
}
);
//添加注释
function enableTooltips(table) {
$('.navtable .ui-pg-button').tooltip({ container: 'body' });
$(table).find('.ui-pg-div').tooltip({ container: 'body' });
}
function beforeDeleteCallback(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;
}
//修改 删除form的样式
function styleDeleteForm(form) {
var buttons = form.next().find('.EditButton .fm-button');
buttons.addClass('btn btn-sm').find('[class*="-icon"]').remove();//ui-icon, s-icon
buttons.eq(0).addClass('btn-danger').prepend('<i class="icon-trash"></i>');
buttons.eq(1).prepend('<i class="icon-remove"></i>');
}
//更新分页图标
function updatePagerIcons() {
var replacement =
{
'ui-icon-seek-first': 'icon-double-angle-left bigger-140',
'ui-icon-seek-prev': 'icon-angle-left bigger-140',
'ui-icon-seek-next': 'icon-angle-right bigger-140',
'ui-icon-seek-end': 'icon-double-angle-right bigger-140'
};
$('.ui-pg-table:not(.navtable) > tbody > tr > .ui-pg-button > .ui-icon').each(function () {
var icon = $(this);
var $class = $.trim(icon.attr('class').replace('ui-icon', ''));
if ($class in replacement) icon.attr('class', 'ui-icon ' + replacement[$class]);
});
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>");
}
}
function styleSearchForm(form) {
var dialog = form.closest('.ui-jqdialog');
var buttons = dialog.find('.EditTable')
buttons.find('.EditButton a[id*="_reset"]').addClass('btn btn-sm btn-info').find('.ui-icon').attr('class', 'icon-retweet');
buttons.find('.EditButton a[id*="_query"]').addClass('btn btn-sm btn-inverse').find('.ui-icon').attr('class', 'icon-comment-alt');
buttons.find('.EditButton a[id*="_search"]').addClass('btn btn-sm btn-purple').find('.ui-icon').attr('class', 'icon-search');
}
function styleSearchFilters(form) {
form.find('.delete-rule').val('X');
form.find('.add-rule').addClass('btn btn-xs btn-primary');
form.find('.add-group').addClass('btn btn-xs btn-success');
form.find('.delete-group').addClass('btn btn-xs btn-danger');
}
//绑定事件 执行删除
$("#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);
}
});
});
</script>
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
- 134.
- 135.
- 136.
- 137.
- 138.
- 139.
- 140.
- 141.
- 142.
- 143.
- 144.
- 145.
- 146.
- 147.
- 148.
- 149.
- 150.
- 151.
- 152.
- 153.
- 154.
- 155.
- 156.
- 157.
- 158.
- 159.
- 160.
- 161.
- 162.
- 163.
- 164.
- 165.
- 166.
- 167.
- 168.
- 169.
- 170.
- 171.
- 172.
- 173.
- 174.
- 175.
- 176.
- 177.
- 178.
- 179.
- 180.
- 181.
- 182.
- 183.
- 184.
- 185.
- 186.
- 187.
- 188.
- 189.
- 190.
- 191.
- 192.
- 193.
- 194.
- 195.
- 196.
- 197.
- 198.
- 199.
- 200.
- 201.
- 202.
- 203.
- 204.
- 205.
- 206.
- 207.
- 208.
- 209.
- 210.
- 211.
- 212.
- 213.
- 214.
- 215.
- 216.
- 217.
- 218.
- 219.
- 220.
- 221.
- 222.
- 223.
- 224.
- 225.
- 226.
- 227.
- 228.
- 229.
- 230.
- 231.
- 232.
- 233.
- 234.
- 235.
- 236.
- 237.
- 238.
- 239.
至此基本告成,还有些可以优化。
如果本文对你有帮助,请霸气的支持下 :) 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/