你的位置:首页 > ASP.net教程

[ASP.net教程]EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(八)


前言

 

  • 本篇幅将对系统的菜单管理模块进行说明,系统的菜单采用树形结构,这样可以更好地方便层级设计和查看。本示例将说明如何通过EntityFramework读取递归的菜单树形结构,以及结合EasyUI的treegrid在Asp.net MVC上显示树形菜单和管理操作。

 

Easyui-treegrid的使用方法

 

  • 首先我们来看一下treegrid的基本使用方法。很简单,和easyui-datagrid差不多。
<table title="Folder Browser" class="easyui-treegrid" style="width:700px;height:250px"      data-options="        url: 'treegrid_data1.json',        method: 'get',        rownumbers: true,        idField: 'id',        treeField: 'name' ">    <thead>      <tr>        <th data-options="field:'name'" width="220">Name</th>        <th data-options="field:'size'" width="100" align="right">Size</th>        <th data-options="field:'date'" width="150">Modified Date</th>      </tr>    </thead>  </table>

 

  • 之前说过data-options可以通过GET方式发送异步请求,读取json数据后就可以加载数据呢。Treegrid中的data-options有两个关键参数idField(主键字段)、treeField(显示字段),上面很明显是利id作为主键字段,name作为显示字段。我们查看一下treegrid_data1.json文件究竟是怎样的格式。 
[{  "id":1,  "name":"C",  "size":"",  "date":"02/19/2010",  "children":[{    "id":2,    "name":"Program Files",    "size":"120 MB",    "date":"03/20/2010",    "children":[{      "id":21,      "name":"Java",      "size":"",      "date":"01/13/2010",      "state":"closed",      "children":[{        "id":211,        "name":"java.exe",        "size":"142 KB",        "date":"01/13/2010"      },{        "id":212,        "name":"jawt.dll",        "size":"5 KB",        "date":"01/13/2010"      }]    },{      "id":22,      "name":"MySQL",      "size":"",      "date":"01/13/2010",      "state":"closed",      "children":[{        "id":221,        "name":"my.ini",        "size":"10 KB",        "date":"02/26/2009"      },{        "id":222,        "name":"my-huge.ini",        "size":"5 KB",        "date":"02/26/2009"      },{        "id":223,        "name":"my-large.ini",        "size":"5 KB",        "date":"02/26/2009"      }]    }]  },{    "id":3,    "name":"eclipse",    "size":"",    "date":"01/20/2010",    "children":[{      "id":31,      "name":"eclipse.exe",      "size":"56 KB",      "date":"05/19/2009"    },{      "id":32,      "name":"eclipse.ini",      "size":"1 KB",      "date":"04/20/2010"    },{      "id":33,      "name":"notice.html",      "size":"7 KB",      "date":"03/17/2005"    }]  }]}]

 

  • 从treegrid_data1.json格式上可以看出还有一个很重要的属性,那就是children,所有的递归的子元素都会包含其中。这和我们的EntityFramework中的对象设计是一致的。所以接下来我们只要通过EntityFramework读取数据后,再利用ASP.NET MVC的json机制序列化出我们需要的json格式就可以绑定到Treegrid上呢。

 

示例中的treegrid使用方法

 

  • 首先,我们定义需要的ASP.NET MVC的Model,treegrid绑定的json数据就是按照此属性来序列化的。参考代码如下:
 public class mod_S_Menu  {    public long ID { get; set; }    public long? PID { get; set; }    public string MenuName { get; set; }    public string Icon { get; set; }    public string Link { get; set; }    public string IsUse { get; set; }    public int Level { get; set; }    public int SerialNO { get; set; }    public string Remark { get; set; }    public List<mod_S_Menu> children { get; set; }  }

 

  • 接下来我们定义菜单操作界面视图MenuList,其中绑定easyui-Treegrid的参考代码如下:
<table id="dg" class="easyui-treegrid" toolbar="#toolbar" style=" height:500px;" fitcolumns="true" singleselect="true"    fit="true"    data-options="        url: '/System/GetMenus',        method: 'get',        lines: true,        rownumbers: true,        idField: 'ID',        treeField: 'MenuName'      ">  <thead>    <tr>      <th data-options="field:'ck',checkbox:true"></th>      <th data-options="field:'ID'" width="50" hidden="true">        主键ID      </th>      <th data-options="field:'MenuName'" width="100">        菜单名称      </th>      <th data-options="field:'Icon'" width="150">        菜单图标      </th>      <th data-options="field:'Link'" width="150">        菜单链接      </th>      <th data-options="field:'IsUse'" width="80">        是否启用      </th>      <th data-options="field:'SerialNO'" width="80">        排序号      </th>      <th data-options="field:'Remark'" width="300">        备注      </th>      <th data-options="field:'PID'" width="50" hidden="true">        父级菜单      </th>    </tr>  </thead></table>

 

  • 接下来,我们通过EntityFramework读取数据,再在SystemController中进行处理,之前说过使用延迟加载会一次性加载出所有与对象相关联的对象。由于S_Menu中的父级菜单ID是子菜单的外键,所以读取数据变得很简单呢。参考代码如下:
    public List<S_Menu> GetInfo()    {      context.Configuration.ProxyCreationEnabled = true;      context.Configuration.LazyLoadingEnabled = true;      List<S_Menu> listData = new List<S_Menu>();      listData = context.S_Menus.Where(x => x.PID.Equals(null)).OrderBy(x => x.SerialNO).ToList();      return listData;    }

 

  • 最后,处理获得的GetInfo集合,因为我们需要序列化出treegrid的识别的json格式,而且我们也希望一次性序列化集合,所以我们可以使用递归的方式来绑定我们需要的数据格式(其实此时的EntityFramework加载的菜单体现的也是一种递归方式)。参考代码如下: 
  public ActionResult GetMenus(string page, string rows)    {      List<S_Menu> listDataParent = IS_Menu.GetInfo();      List<mod_S_Menu> DataModel = new List<mod_S_Menu>();      foreach (var item in listDataParent)      {        mod_S_Menu model = new mod_S_Menu();        model.ID = item.ID;        model.PID = item.PID;        model.Icon = item.Icon;        model.IsUse = item.IsUse;        model.Level = item.Level;        model.Link = item.Link;        model.MenuName = item.MenuName;        model.SerialNO = item.SerialNO;        model.Remark = item.Remark;        model.children = new List<mod_S_Menu>();        GetRecursion(model, item);  //递归        DataModel.Add(model);      }      return Json(DataModel, JsonRequestBehavior.AllowGet);    }    protected void GetRecursion(mod_S_Menu model,S_Menu item)    {      var children = item.Children.OrderBy(x => x.SerialNO).ToList();      foreach (var childitem in children)      {        mod_S_Menu childmodel = new mod_S_Menu();        childmodel.ID = childitem.ID;        childmodel.PID = childitem.PID;        childmodel.Icon = childitem.Icon;        childmodel.IsUse = childitem.IsUse;        childmodel.Level = childitem.Level;        childmodel.Link = childitem.Link;        childmodel.MenuName = childitem.MenuName;        childmodel.SerialNO = childitem.SerialNO;        childmodel.Remark = childitem.Remark;        childmodel.children = new List<mod_S_Menu>();        model.children.Add(childmodel);        GetRecursion(childmodel, childitem); //递归      }    }

 

  • 到此,我们通过treegrid加载出我们想要的树形结构数据呢。执行以下数据脚本:
INSERT [dbo].[S_Menu] ([ID], [MenuName], [Icon], [Link], [IsUse], [Level], [SerialNO], [PID], [Remark]) VALUES (150704103806185, N'系统权限管理', N'icon-large-chart', N'', N'是', 1, 1, NULL, N'设置权限管理的以及菜单')INSERT [dbo].[S_Menu] ([ID], [MenuName], [Icon], [Link], [IsUse], [Level], [SerialNO], [PID], [Remark]) VALUES (150706103806185, N'基本数据设置', N'asd', N'/bb/sss', N'是', 1, 2, NULL, N'基础数据管理')INSERT [dbo].[S_Menu] ([ID], [MenuName], [Icon], [Link], [IsUse], [Level], [SerialNO], [PID], [Remark]) VALUES (150704103806181, N'用户管理', N'icon-large-picture', N'/System/UserList', N'是', 2, 1, 150704103806185, N'asd')INSERT [dbo].[S_Menu] ([ID], [MenuName], [Icon], [Link], [IsUse], [Level], [SerialNO], [PID], [Remark]) VALUES (150704103806182, N'角色管理', N'icon-large-clipart', N'/System/RoleList', N'是', 2, 2, 150704103806185, NULL)INSERT [dbo].[S_Menu] ([ID], [MenuName], [Icon], [Link], [IsUse], [Level], [SerialNO], [PID], [Remark]) VALUES (150706162942028, N'test1', N'test1', N'test1', N'是', 1, 3, NULL, N'asadas')INSERT [dbo].[S_Menu] ([ID], [MenuName], [Icon], [Link], [IsUse], [Level], [SerialNO], [PID], [Remark]) VALUES (150706163404518, N'test12', N'test12', N'test12', N'是', 2, 2, 150706162942028, N'assadasd')INSERT [dbo].[S_Menu] ([ID], [MenuName], [Icon], [Link], [IsUse], [Level], [SerialNO], [PID], [Remark]) VALUES (150708114022584, N'菜单管理', N'icon-large-shapes', N'/System/MenuList', N'是', 2, 3, 150704103806185, NULL)INSERT [dbo].[S_Menu] ([ID], [MenuName], [Icon], [Link], [IsUse], [Level], [SerialNO], [PID], [Remark]) VALUES (150708114134082, N'权限设置', N'icon-large-smartart', N'/System/PermitList', N'是', 2, 4, 150704103806185, NULL)INSERT [dbo].[S_Menu] ([ID], [MenuName], [Icon], [Link], [IsUse], [Level], [SerialNO], [PID], [Remark]) VALUES (150706103806181, N'承包合同数据录入', N'ss', N'/ss/ssss', N'是', 2, 1, 150706103806185, N'线程')

 

  • 运行效果如下:

  

  • 本节示例代码已放置网盘,点击下载