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="">Name</th>
<th data-options="field:'size'" width="" align="right">Size</th>
<th data-options="field:'date'" width="">Modified Date</th>
</tr>
</thead>
</table>
- 之前说过data-options可以通过GET方式发送异步请求,读取json数据后就可以加载数据呢。Treegrid中的data-options有两个关键参数idField(主键字段)、treeField(显示字段),上面很明显是利id作为主键字段,name作为显示字段。我们查看一下treegrid_data1.json文件究竟是怎样的格式。
[{
"id":,
"name":"C",
"size":"",
"date":"02/19/2010",
"children":[{
"id":,
"name":"Program Files",
"size":"120 MB",
"date":"03/20/2010",
"children":[{
"id":,
"name":"Java",
"size":"",
"date":"01/13/2010",
"state":"closed",
"children":[{
"id":,
"name":"java.exe",
"size":"142 KB",
"date":"01/13/2010"
},{
"id":,
"name":"jawt.dll",
"size":"5 KB",
"date":"01/13/2010"
}]
},{
"id":,
"name":"MySQL",
"size":"",
"date":"01/13/2010",
"state":"closed",
"children":[{
"id":,
"name":"my.ini",
"size":"10 KB",
"date":"02/26/2009"
},{
"id":,
"name":"my-huge.ini",
"size":"5 KB",
"date":"02/26/2009"
},{
"id":,
"name":"my-large.ini",
"size":"5 KB",
"date":"02/26/2009"
}]
}]
},{
"id":,
"name":"eclipse",
"size":"",
"date":"01/20/2010",
"children":[{
"id":,
"name":"eclipse.exe",
"size":"56 KB",
"date":"05/19/2009"
},{
"id":,
"name":"eclipse.ini",
"size":"1 KB",
"date":"04/20/2010"
},{
"id":,
"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="" hidden="true">
主键ID
</th>
<th data-options="field:'MenuName'" width="">
菜单名称
</th>
<th data-options="field:'Icon'" width="">
菜单图标
</th>
<th data-options="field:'Link'" width="">
菜单链接
</th>
<th data-options="field:'IsUse'" width="">
是否启用
</th>
<th data-options="field:'SerialNO'" width="">
排序号
</th>
<th data-options="field:'Remark'" width="">
备注
</th>
<th data-options="field:'PID'" width="" 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 (, N'系统权限管理', N'icon-large-chart', N'', N'是', , , NULL, N'设置权限管理的以及菜单')
INSERT [dbo].[S_Menu] ([ID], [MenuName], [Icon], [Link], [IsUse], [Level], [SerialNO], [PID], [Remark]) VALUES (, N'基本数据设置', N'asd', N'/bb/sss', N'是', , , NULL, N'基础数据管理')
INSERT [dbo].[S_Menu] ([ID], [MenuName], [Icon], [Link], [IsUse], [Level], [SerialNO], [PID], [Remark]) VALUES (, N'用户管理', N'icon-large-picture', N'/System/UserList', N'是', , , , N'asd')
INSERT [dbo].[S_Menu] ([ID], [MenuName], [Icon], [Link], [IsUse], [Level], [SerialNO], [PID], [Remark]) VALUES (, N'角色管理', N'icon-large-clipart', N'/System/RoleList', N'是', , , , NULL)
INSERT [dbo].[S_Menu] ([ID], [MenuName], [Icon], [Link], [IsUse], [Level], [SerialNO], [PID], [Remark]) VALUES (, N'test1', N'test1', N'test1', N'是', , , NULL, N'asadas')
INSERT [dbo].[S_Menu] ([ID], [MenuName], [Icon], [Link], [IsUse], [Level], [SerialNO], [PID], [Remark]) VALUES (, N'test12', N'test12', N'test12', N'是', , , , N'assadasd')
INSERT [dbo].[S_Menu] ([ID], [MenuName], [Icon], [Link], [IsUse], [Level], [SerialNO], [PID], [Remark]) VALUES (, N'菜单管理', N'icon-large-shapes', N'/System/MenuList', N'是', , , , NULL)
INSERT [dbo].[S_Menu] ([ID], [MenuName], [Icon], [Link], [IsUse], [Level], [SerialNO], [PID], [Remark]) VALUES (, N'权限设置', N'icon-large-smartart', N'/System/PermitList', N'是', , , , NULL)
INSERT [dbo].[S_Menu] ([ID], [MenuName], [Icon], [Link], [IsUse], [Level], [SerialNO], [PID], [Remark]) VALUES (, N'承包合同数据录入', N'ss', N'/ss/ssss', N'是', , , , N'线程')
- 运行效果如下:
- 本节示例代码已放置网盘,点击下载。
EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(八)的更多相关文章
- EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(一)
前言 本系列源自对EF6 CodeFirst的探索,但后来发现在自己项目中构建的时候遇到了一些问题以及一些解决方法,因此想作为一个系列写下来. 本系列并不是教你怎么做架构设计,但可以参照一下里面的方法 ...
- EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(六)
前言 在接下来的篇幅里将对系统的模块功能进行编写.主要以代码实现为主.这一篇我们需要完成系统模块“角色管理”的相关功能.完成后可以对系统框架结构有进一步了解. Abstract层 之前说过,Abstr ...
- EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(完)
前言 这一篇是本系列的最后一篇,虽然示例讲到这里就停止呢,但对于这些技术的学习远不能停止.虽然本示例讲的比较基础,但是正如我第一篇说到的,这个系列的目的不是说一些高端的架构设计,而是作为一个入门级,对 ...
- EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(七)
前言 上一篇文章我们完成了系统角色管理的基本功能实现,也对系统层次结构进行了了解.这一篇我们将继续对系统的用户管理模块进行代码编写.代码没有做封装,所以大部分的逻辑代码都是相通的,只是在一些前端的细节 ...
- EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(四)
前言 这一篇,我们终于到了讲解Entity Framework CodeFirst 的时刻了,首先创建实体对象模型,然后会通过配置Fluent API的方式来对实体对象模型进行完整的数据库映射操作. ...
- EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(三)
前言 在上一篇中,我们依靠着EasyUI强大的前端布局特性把前端登录界面和主界面给搭建完成了.这一篇我们就要尝试着把整个解决方案部署到云端呢,也就是Visual Studio Online(TFVC) ...
- EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(二)
前言 写完第一篇后,我一直在想接下来应该从哪一方面开始讲.后来我觉得不用那么死板的把每一个课程和大纲都列出来吧,毕竟我又不是教书的,呵呵...我觉得就像做实验一样,我们一部分一部分的完成,最后总个结果 ...
- EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(九)
前言 这一篇我们将完成系统的权限设置功能以及不同角色用户登录系统后动态加载菜单.注意:此示例权限只针对菜单级,如果园友需要更复杂的系统权限设置,可以拓展到按钮级或属性级. 用户的登录采用Form认证来 ...
- EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(五)
前言 在编写代码的时候,我遇到了很多关于EntityFramework6的疑问,所以现在就提前把这些问题列出来做一下解答,以便在以后的代码编写过程中减少不必要的Bug. EntityFramework ...
随机推荐
- append追加的使用
#!/usr/bin/env python def fun(arg) : ret = [] for i in range(len(arg)) : if i % 2 ==1 : ret.append(a ...
- exel中合并一列相同的数据到一行
Sub 按钮1_Click() Application.ScreenUpdating = False arr = Range("a1:c" & [a65536].End(x ...
- 剑指offer五:
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则. /* public class ListNode { int val; ListNode next = n ...
- 16-腾讯-intership-面试
问题 问:说一下在浏览器那里输入一个网址,会发生什么?答:DNS服务器解析,TCP三次握手,建立连接,然后bilibala............... 问:你对http相关协议熟悉吗?答:我问是ge ...
- JS中parseInt()、Numer()深度解析
JS中字符串转换为数字有两种方式: 1.parseInt函数 定义:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/ ...
- godep 包管理工具
godep是解决包依赖的管理工具 安装 go get github.com/tools/godep 成功安装后,在GOPATH的bin目录下会有一个godep可执行的二进制文件,后面执行的命令都是用这 ...
- 插件开发-UI插件开发
1.新建类库解决方案,引入命名空间,同时引入要添加UI Form的WebPart(在Portal\UILib目录下) 2.继续UFSoft.UBF.UI.Custom.ExtendedPartBase ...
- RecyclerView 制作瀑布流图片
这是瀑布流的效果图 RecyclerView(ListView的升级版) 加载图片用的是第三方图片加载框架 ------------------------------------- 在Xml中 &l ...
- iOS - SQLite 数据库存储
1.SQLite 数据库 SQLite 是一种轻型的嵌入式数据库,安卓和 iOS 开发使用的都是 SQLite 数据库.它占用资源非常低,在嵌入式设备中,可能需要几百 K 的内存数据就够了.他的处理速 ...
- 《C++ Primer》学习笔记【第三部分 类设计者的工具】
第13章 拷贝控制 使用default:=defult只能修饰默认构造函数或拷贝控制成员,显式地要去编译器生成合成的版本. 使用delete:=delete通知编译器不希望定义这些成员,禁止试图使用它 ...