delphi cxTreeList 实现动态多级菜单的功能
创建 Menu 表
CREATE TABLE Menu ( MenuID INT PRIMARY KEY, ParentMenuID INT NULL, Title NVARCHAR(100) NOT NULL, URL NVARCHAR(255), OrderNumber INT, IsActive BIT NOT NULL DEFAULT 1, );
插入示例数据
INSERT INTO Menu (MenuID, ParentMenuID, Title, URL, OrderNumber, IsActive) VALUES (1, 0, '主页', '/', 1, 1), (2, 0, '博客', '/blog', 2, 1), (3, 0, '关于我们', '/about', 3, 1), (4, 0, '联系我们', '/contact', 4, 1), (5, 2, '技术', '/blog/tech', 1, 1), (6, 5, 'SQL Server', '/blog/tech/sqlserver', 1, 1), (7, 5, 'Python', '/blog/tech/python', 2, 1), (8, 2, '文学', '/blog/literature', 2, 1), (9, 3, '公司简介', '/about/company-profile', 1, 1), (10, 9, '我们的历史', '/about/company-history', 1, 1), (11, 9, '我们的团队', '/about/company-team', 2, 1);
实现代码,已经加了详细注释
procedure TForm1.load_menu; var Node, ParentNode: TcxTreeListNode; MenuItemID, ParentID: Integer; // 定义一个递归函数,用于在树节点中查找指定ID的节点 function FindNodeByID(RootNode: TcxTreeListNode; NodeID: Integer): TcxTreeListNode; var I: Integer; Node: TcxTreeListNode; begin Result := nil; // 遍历当前节点的所有子节点 for I := 0 to RootNode.Count - 1 do begin Node := RootNode.Items[I]; // 如果找到节点ID匹配的节点,则返回该节点 if Node.Values[0] = NodeID then begin Result := Node; Exit; // 退出函数 end; // 否则递归地在当前子节点中查找 Result := FindNodeByID(Node, NodeID); // 如果找到了匹配的节点,则直接返回结果 if Assigned(Result) then Exit; // 退出函数 end; end; begin // 关闭查询,清除SQL语句,设置新的查询语句 FDQuery1.Close; FDQuery1.SQL.Clear; FDQuery1.SQL.Add('SELECT MenuID, ParentMenuID, Title FROM db.dbo.Menu ORDER BY MenuID'); FDQuery1.Open; // 如果查询结果不为空,则开始处理 if not FDQuery1.IsEmpty then begin FDQuery1.First; // 定位到查询结果的第一条记录 // 遍历查询结果的每一条记录 while not FDQuery1.Eof do begin MenuItemID := FDQuery1.FieldByName('MenuID').AsInteger; // 获取菜单ID ParentID := FDQuery1.FieldByName('ParentMenuID').AsInteger; // 获取父菜单ID // 根据父菜单ID确定父节点 if ParentID = 0 then ParentNode := cxTreeList1.Root // 如果父菜单ID为0,则父节点是根节点 else ParentNode := FindNodeByID(cxTreeList1.Root, ParentID); // 否则通过递归查找父节点 // 如果找到了父节点,则添加当前菜单节点作为其子节点 if Assigned(ParentNode) then begin Node := cxTreeList1.AddChild(ParentNode); // 添加子节点 Node.Values[0] := MenuItemID; // 设置节点的第一列值为菜单ID Node.Values[1] := FDQuery1.FieldByName('Title').AsString; // 设置节点的第二列值为菜单标题 Node.Values[2] := FDQuery1.FieldByName('Url').AsString; // 设置节点的第二列值为导航地址 end; FDQuery1.Next; // 移动到查询结果的下一条记录 end; end; end;
效果
本文来自博客园,作者:liessay,转载请注明原文链接:https://www.cnblogs.com/liessay/p/18273998
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
2020-06-28 Vue状态管理Vuex简单使用
2020-06-28 Vue 路由跳转报错 Error: Avoided redundant navigation to current location: "/XXX".