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