Мне нужно отобразить главное меню в TVirtualStringTree - каждый элемент меню имеет категорию. Категории будут составлять корневые узлы дерева, а под каждым корневым узлом категории будут элементы меню.VirtualStringTree - Не удается корректно работать с родительскими дочерними узлами
наборов данных для полей Категории и MenuItems выглядеть следующим образом:
Мой код в OnInitNode прокручивается через записях Категория набора данных и загружает эти пункты меню для каждой категории в качестве дочерних узлов. Однако у меня что-то не так (см. Изображение), а узлы категории - это один и тот же текст, что означает, что набор данных не прокручивается до следующей записи.
Кажется, что эта строка кода в InitNode
событие вызывает его, чтобы выйти из цикла и, как представляется, является причиной проблемы:
Sender.ChildCount[Node] := x;
Но то, что это правильный путь, чтобы сделать дочерние узлы ?
Это мой код:
type
TTreeCategoryData = record
ID: Integer;
DispText: String;
end;
PTreeCategoryData = ^TTreeCategoryData;
TTreeMenuItemData = record
ID: Integer;
CategoryID: Integer;
DispText: String;
ClassName: String;
end;
PTreeMenuItemData = ^TTreeMenuItemData;
Tvstmainmenu_CategoryNodeData = record
TreeCategoryData: PTreeCategoryData;
end;
Pvstmainmenu_CategoryNodeData = ^Tvstmainmenu_CategoryNodeData;
Tvstmainmenu_MenuItemNodeNodeData = record
TreeMenuItemData: PTreeMenuItemData;
end;
Pvstmainmenu_MenuItemNodeNodeData = ^Tvstmainmenu_MenuItemNodeNodeData;
procedure TfmMain.FormShow(Sender: TObject);
var
x: Integer;
begin
datamod.uspspmenucatgy_S.PrepareSQL(True);
datamod.uspspmenucatgy_S.Open;
x := datamod.uspspmenucatgy_S.RecordCount;
vstmainmenu.RootNodeCount := x;
end;
procedure TfmMain.vstmainmenuFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
var
CategoryNodeData: Pvstmainmenu_CategoryNodeData;
MenuItemNodeNodeData: Pvstmainmenu_MenuItemNodeNodeData;
begin
if (Sender.GetNodeLevel(Node) = 0) then
begin
CategoryNodeData := Sender.GetNodeData(Node);
if Assigned(CategoryNodeData) and Assigned(CategoryNodeData.TreeCategoryData) then
begin
Dispose(CategoryNodeData.TreeCategoryData);
end;
end
else if (Sender.GetNodeLevel(Node) = 1) then
begin
MenuItemNodeNodeData := Sender.GetNodeData(Node);
if Assigned(MenuItemNodeNodeData) and Assigned(MenuItemNodeNodeData.TreeMenuItemData) then
begin
Dispose(MenuItemNodeNodeData.TreeMenuItemData);
end;
end;
end;
procedure TfmMain.vstmainmenuGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex;
TextType: TVSTTextType; var CellText: string);
var
CategoryNodeData: Pvstmainmenu_CategoryNodeData;
MenuItemNodeNodeData: Pvstmainmenu_MenuItemNodeNodeData;
TreeCategoryData: PTreeCategoryData;
TreeMenuItemData: PTreeMenuItemData;
begin
if (Sender.GetNodeLevel(Node) = 0) then
begin
CategoryNodeData := Sender.GetNodeData(Node);
if Assigned(CategoryNodeData) and Assigned(CategoryNodeData.TreeCategoryData) then
begin
TreeCategoryData := CategoryNodeData.TreeCategoryData;
CellText := TreeCategoryData^.DispText;
end;
end
else if (Sender.GetNodeLevel(Node) = 1) then
begin
MenuItemNodeNodeData := Sender.GetNodeData(Node);
if Assigned(MenuItemNodeNodeData) and Assigned(MenuItemNodeNodeData.TreeMenuItemData) then
begin
TreeMenuItemData := MenuItemNodeNodeData.TreeMenuItemData;
CellText := TreeMenuItemData^.DispText;
end;
end;
end;
procedure TfmMain.vstmainmenuInitNode(Sender: TBaseVirtualTree; ParentNode, Node: PVirtualNode;
var InitialStates: TVirtualNodeInitStates);
var
CategoryNodeData: Pvstmainmenu_CategoryNodeData;
MenuItemNodeNodeData: Pvstmainmenu_MenuItemNodeNodeData;
x: Integer;
begin
if (Sender.GetNodeLevel(Node) = 0) then
begin
CategoryNodeData := Sender.GetNodeData(Node);
CategoryNodeData.TreeCategoryData := New(PTreeCategoryData);
with CategoryNodeData.TreeCategoryData^ do
begin
ID := datamod.uspspmenucatgy_Srow_id.AsInteger;
DispText := datamod.uspspmenucatgy_Scategory.AsString;
end;
// :Pcategory_id
datamod.uspspmenu_S.ParamByName('Pcategory_id').AsInteger := datamod.uspspmenucatgy_Srow_id.AsInteger;
datamod.uspspmenu_S.PrepareSQL(True);
if (datamod.uspspmenu_S.State = dsBrowse) then
datamod.uspspmenu_S.Refresh
else
datamod.uspspmenu_S.Open;
x := datamod.uspspmenu_S.RecordCount;
Sender.ChildCount[Node] := x;
datamod.uspspmenucatgy_S.Next;
end
else if (Sender.GetNodeLevel(Node) = 1) then
begin
MenuItemNodeNodeData := Sender.GetNodeData(Node);
MenuItemNodeNodeData.TreeMenuItemData := New(PTreeMenuItemData);
with MenuItemNodeNodeData.TreeMenuItemData^ do
begin
ID := datamod.uspspmenu_Srow_id.AsInteger;
CategoryID := datamod.uspspmenucatgy_Srow_id.AsInteger;
DispText := datamod.uspspmenu_Smenuitem.AsString;
ClassName := datamod.uspspmenu_Stframeclass.AsString;
end;
datamod.uspspmenu_S.Next;
end;
end;
Вот что происходит. Каждый корневой узел (родительский) должен быть другим, но это не так. Дальше дочерние узлы для 2-го корневого узла должны быть разными, но это, кажется, застрял на последнем дочернего узла 1-го корневого узла:
Спасибо заранее!
Спасибо! Он работал правильно. –