前言
- 本篇幅將對系統的菜單管理模塊進行說明,系統的菜單采用樹形結構,這樣可以更好地方便層級設計和查看。本示例將說明如何通過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'線程')
- 運行效果如下:
- 本節示例代碼已放置網盤,點擊下載。