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)。


下载全部源代码


posted @   三生石上(FineUI控件)  阅读(11418)  评论(17编辑  收藏  举报
编辑推荐:
· 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,谁才是开发者新宠?
点击右上角即可分享
微信分享提示