Hi!
I need to iterate a treeview component to update a table with it's data.
I fill the tree like this (after creating all necessary stuff):
while not FDQuery1.Eof do
begin
// ('2');
if cl <> (FDQuery1.FieldByName('Class').AsString) then
begin
pn := AdvTreeView1.AddNode(tn);
pn.Text[0] := FDQuery1.FieldByName('Class').AsString;
pn.Extended := True;
end;
// ('3');
if rn <> (FDQuery1.FieldByName('Name').AsString) then
begin
rt := '';
n := AdvTreeView1.AddNode(pn);
n.Text[0] := FDQuery1.FieldByName('Name').AsString;
// n.DataString := FDQuery1.FieldByName('RiskName').AsString;
n.Extended := True;
end;
// ('4');
if rt <> (FDQuery1.FieldByName('Type').AsString) then
begin
de := '';
subn := AdvTreeView1.AddNode(n);
subn.Text[0] := FDQuery1.FieldByName('Type').AsString;
subn.Extended := True;
end;
// ('5');
if de <> (FDQuery1.FieldByName('Description').AsString) then
begin
ssubn := AdvTreeView1.AddNode(subn);
ssubn.Text[0] := FDQuery1.FieldByName('Description').AsString;
ssubn.Text[1] := FDQuery1.FieldByName('Effects').AsString;
ssubn.Text[2] := FDQuery1.FieldByName('Status').AsString;
ssubn.Extended := False;
end;
// ('6');
cl := FDQuery1.FieldByName('Class').AsString;
rn := FDQuery1.FieldByName('Name').AsString;
rt := FDQuery1.FieldByName('Type').AsString;
de := FDQuery1.FieldByName('Description').AsString;
FDQuery1.Next;
end;
After the user changes Status column I need to iterate all nodes at this level and use ssubn.Text[0] and ssubn.Text[1] to update table.
I have tried with
lvl1 := AdvTreeView1.GetFirstRootNode;
lvl2 := AdvTreeView1.GetFirstChildNode(lvl1);
lvl3 := AdvTreeView1.GetFirstChildNode(lvl2);
chld1 := AdvTreeView1.GetFirstChildNode(lvl3);
while Assigned(chld1) do
begin
Memo1.Lines.Add('Child 1: ' + chld1.Text[0]);
chld1 := chld1.GetNext;
end;
but I also get the Type in all but the first level when I only want Description and Effects.
Any idea how to get this right?
Best Regards
Francisco Alvarado
To traverse the node tree you need to start with AdvTreeView1.GetFirstRootNode, as you did in your sample. If you want the next node on the same level, you call AdvTreeView1.GetNextSibling, and the parameter is the previous node. If you want to go down a level, you need to call AdvTreeView1.GetFirstChildNode. You can also directly call GetNextSibling on the node itself without parameters, which makes it easier to follow. Below is a sample that shows all nodes at three levels (ROOT level, sub level 1, sub level 2)
var
n, ns, nss: TAdvTreeViewNode;
begin
n := AdvTreeView1.GetFirstRootNode;
//level 0 (ROOT)
while Assigned(n) do
begin
OutputDebugString(pchar(n.Text[0]));
ns := n.GetFirstChild;
//level 1
while Assigned(ns) do
begin
OutputDebugString(pchar(' '+ns.Text[0]));
nss := ns.GetFirstChild;
//level 2
while Assigned(nss) do
begin
OutputDebugString(pchar(' '+nss.Text[0]));
nss := nss.GetNextSibling;
end;
ns := ns.GetNextSibling;
end;
n := n.GetNextSibling;
end;
Thank you Pieter!
... and sorry for the delay in reading your solution.
Now I'm trying to set several advTreeView components in read-only mode based on the user's rights..
If I use enabled := False then the scroll bars are not working and the users can't see all nodes.
Is there a workaround to simulate a red-only status for the AdvTreeView?
Best Regards
Francisco Alvarado
If you mean read-only in no editing, then there is no editing available by default. If you mean also to not allow selection/interaction, but only scrolling then you can use Interaction.ReadOnly in combination with disabled selection:
procedure TForm1.AdvTreeView1BeforeSelectNode(Sender: TObject;
ANode: TAdvTreeViewVirtualNode; var ACanSelect: Boolean);
begin
ACanSelect := False;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
AdvTreeView1.Interaction.ReadOnly := True;
end;
Thank you Pieter!
I decided to perform the edits defining editors in the appropriate columns so I just use this:
procedure TRskRegisterF1.AdvTreeView1BeforeOpenInplaceEditor(Sender: TObject; ANode: TAdvTreeViewVirtualNode; AColumn: Integer;
var ACanOpen: Boolean);
begin
ACanOpen := IsEditing;
end;