ExtAspNet应用技巧(十五) - 树形菜单与手风琴式菜单
界面截图
手风琴式菜单

树形菜单

数据库表(X_Menu)
设计视图:

数据:

ASPX标签定义
在上一篇文章中已经对前台页面定义有了详细的描述。
1 2 3 | < ext:Region ID="regionLeft" Split="true" Width="200px" Margins="0 0 0 0" ShowHeader="true" Title="菜单" EnableCollapse="true" Layout="Fit" Position="Left" runat="server"> </ ext:Region > |
动态创建树形菜单
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 | protected void Page_Init( object sender, EventArgs e) { InitMenu(); } private void InitMenu() { XMenuCollection menus = new Select().From<XMenu>() .Where(XMenu.ShowColumn).IsEqualTo( true ) .OrderAsc(XMenu.SortIndexColumn.ColumnName) .ExecuteAsCollection<XMenuCollection>(); if (XConfigHelper.MenuType.ToLower() == "accordion" ) { // TODO 创建手风琴式菜单 } else { ExtAspNet.Tree tree = new ExtAspNet.Tree(); regionLeft.Items.Add(tree); tree.ShowBorder = false ; tree.ShowHeader = false ; tree.AutoScroll = true ; tree.EnableArrows = true ; ResolveMenuTree(menus, 0, tree.Nodes); } } /// <summary> /// 生成菜单树 /// </summary> /// <param name="menus"></param> /// <param name="parentMenuId"></param> /// <param name="nodes"></param> /// <returns>当前节点的子节点个数</returns> private int ResolveMenuTree(XMenuCollection menus, int parentMenuId, ExtAspNet.TreeNodeCollection nodes) { int count = 0; foreach (XMenu menu in menus) { if (menu.ParentMenuId == parentMenuId) { ExtAspNet.TreeNode node = new ExtAspNet.TreeNode(); nodes.Add(node); node.Text = menu.Name; node.IconUrl = menu.ImageUrl; if (!String.IsNullOrEmpty(menu.NavigateUrl)) { node.NavigateUrl = menu.NavigateUrl; node.Target = "main" ; } int childCount = ResolveMenuTree(menus, menu.Id, node.Nodes); if (childCount == 0) { node.Leaf = true ; } count++; } } return count; } |
在这段代码中,有几点需要注意的地方:
- 由于需要动态创建控件,所以最好放在Page_Init中而不是Page_Load
- 使用SubSonic从数据库检索数据相当方便,这里只检索需要显示的菜单
- ResolveMenuTree用于递归生成Tree控件,特别注意这里通过返回值来标示当前节点的子节点数,从而为node.Leaf赋值
创建手风琴式菜单
下面看下 “// TODO 创建手风琴式菜单” 的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | ExtAspNet.Accordion accordion = new ExtAspNet.Accordion(); regionLeft.Items.Add(accordion); accordion.ShowBorder = false ; accordion.ShowHeader = false ; foreach (XMenu menu in menus) { if (menu.ParentMenuId == 0) { ExtAspNet.AccordionPane pane = new ExtAspNet.AccordionPane(); accordion.Panes.Add(pane); pane.Title = menu.Name; pane.ShowBorder = false ; ExtAspNet.Tree tree = new ExtAspNet.Tree(); pane.Items.Add(tree); tree.ShowBorder = false ; tree.ShowHeader = false ; tree.AutoScroll = true ; tree.EnableArrows = true ; ResolveMenuTree(menus, menu.Id, tree.Nodes); } } |
通过所有的一级菜单(menu.ParentMenuId == 0)创建Accordion控件,然后二级以下菜单创建AccordionPane中的子控件 - Tree。
下一章,我们使用Grid控件来完成“菜单管理”模块,包括菜单的增删改查(CRUD)。
下载全部源代码
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?