问题
I have a tcxTreeList with 3 columns the first column has set property of
Node.CheckGroupType := ncgCheckGroup;
, and 2nd column contains Key of the First root node and third column contains the keys of all child nodes under the root node.
How can i get the key of root node whether it is checked or not and keys of all checked child nodes into 2 variables to insert into db and Load back items from keys we get from DB
My code for adding items is as below
APNode := tv.Add;
APNode.CheckGroupType := ncgCheckGroup;
APNode.Values[0] := define;
ApNode.Values[1] := dCode;
define - contains Text like Created, Released,In-Active etc.. all Root nodes dcode - contains key value of each root node like E,F,I,P,R
This is how i added child nodes for each root node
procedure TF_Form1.addPStatsToTreeList(tl: TcxTreeList; const dcode, define: string);
function AddTreeListNode(TreeList: TcxTreeList; APNode: TcxTreeListNode; const AValues: Array of Variant; AImageIndex: Integer): TcxTreeListNode;
begin
Result := TreeList.AddChild(APNode);
Result.AssignValues(AValues);
Result.Imageindex := AImageIndex;
end;
var
grpnode,chNode, ANode: TcxTreeListNode;
icnt : integer;
begin
icnt := tl.Count;
if Assigned(tl) then
begin
ANode := tl.TopNode;
while ANode <> nil do
begin
ANode := AddTreeListNode(tl, ANode, [define, '', dcode], 0);
ANode := TcxTreeListNode(ANode.GetNext);
end;
end;
end;
UPDATE
dcode is a single letter and Definition is a string, Dcode is the key for string in definition, Like a key-value pair Dcode is key and definition is value.
In the tree list root nodes like Created, Released, In Active, Checked and Reactivated have different Key which is in column1 and key for subnode values like Sample, Development, Production etc.. is in 3rd column.
Only Key values are saved to DB, root node keys are saved directly whether they are Checked or not. Each root node key will be saved to different rows and coming to subnodes only Checked nodes keys are saved to DB with comma separated.
For Example . If Root node Created and items under it like Sample , Development are checked then root node key E
is one column[DEFCODE(Primarykey)] and subnodes keys M,E
(DEFINITION) with coma separated are in other column.
回答1:
The code below shows how to save to a TClientDataSet the Checked state of a root node along with its key and a comma-separated list of the keys of its children which are checked using the method SaveTreeState.
The method LoadTreeState clears the Checked state of each node in the ctTreeList and then re-loads the saved Checked states from the CDS.
To use this code you need to add a TClientDataSet named CDS1 to your project, and a TDataSource and TDBGrid wired up in the usual way. Then add persistent fields to the CDS as shown in the code, compile and run.
I hope I've understood how your cxTreeList is set up correctly, but if not, hopefully the code should be pretty straightforward to adapt to what you are actually doing.
type
TForm1 = class(TForm)
cxTreeList1: TcxTreeList;
CDS1: TClientDataSet;
btnLoad: TButton;
cxTreeList1Column1: TcxTreeListColumn;
cxTreeList1Column2: TcxTreeListColumn;
cxTreeList1Column3: TcxTreeListColumn;
DataSource1: TDataSource;
DBGrid1: TDBGrid;
CDS1RootKey: TStringField; // String[1]
CDS1CheckedChildKeys: TStringField; // String[20]
CDS1RootNodeChecked: TBooleanField;
btnClear: TButton;
procedure btnClearClick(Sender: TObject);
procedure btnLoadClick(Sender: TObject);
procedure btnSaveClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
procedure SaveTreeState;
procedure ClearChecks;
procedure LoadTreeState;
end;
[...]
procedure TForm1.ClearChecks;
var
i,
j : Integer;
begin
for i := 0 to cxTreeList1.Count - 1 do begin
cxTreeList1.Items[i].Checked := False;
for j := 0 to cxTreeList1.Items[i].Count - 1 do begin
cxTreeList1.Items[i].Items[j].Checked := False;
end;
end;
end;
procedure TForm1.SaveTreeState;
var
i,
j : Integer;
RootNode,
ChildNode : TcxTreeListNode;
RootKey,
ChildKeys : String;
begin
CDS1.DisableControls;
try
CDS1.EmptyDataSet;
for i := 0 to cxTreeList1.Count - 1 do begin
RootNode := cxTreeList1.Items[i];
RootKey := RootNode.Values[1];
ChildKeys := '';
for j := 0 to RootNode.Count - 1 do begin
ChildNode := RootNode.Items[j];
if ChildNode.Checked then begin
if ChildKeys <> '' then
ChildKeys := ChildKeys + ',';
ChildKeys := ChildKeys + ChildNode.Values[2];
end;
end;
CDS1.InsertRecord([RootKey, ChildKeys, RootNode.Checked]);
end;
finally
CDS1.EnableControls;
end;
end;
procedure TForm1.LoadTreeState;
var
RootKey,
ChildKey : String;
ChildKeys : TStringList;
i : Integer;
RootNode,
ChildNode : TcxTreeListNode;
function FindRootNodeByKey(const Key : String) : TcxTreeListNode;
var
i : Integer;
begin
for i := 0 to cxTreeList1.Count - 1 do begin
Result := cxTreeList1.Items[i];
if CompareText(Result.Values[1], Key) = 0 then
Exit;
end;
Result := Nil;
end;
function FindChildNodeByKey(ParentNode : TcxTreeListNode; const Key : String) : TcxTreeListNode;
var
i : Integer;
begin
for i := 0 to ParentNode.Count - 1 do begin
Result := ParentNode.Items[i];
if CompareText(Result.Values[2], Key) = 0 then
Exit;
end;
Result := Nil;
end;
begin
cxTreeList1.BeginUpdate; // prevent treelist from updating while we load its state
ClearChecks;
try
// ChildKeys is a TStringList that we'll use to parse the list of child keys into individual values
ChildKeys := TStringList.Create;
try
CDS1.DisableControls;
try
CDS1.First;
while not CDS1.Eof do begin
RootKey := CDS1RootKey.AsString;
RootNode := FindRootNodeByKey(RootKey);
Assert(RootNode <> Nil); // check that we found the root node
RootNode.Checked := CDS1RootNodeChecked.AsBoolean;
ChildKeys.CommaText := Trim(CDS1CheckedChildKeys.AsString); // Loading ChildKeys
// by this assignment is what causes it to be parsed into individual keys
for i := 0 to ChildKeys.Count - 1 do begin
ChildKey := ChildKeys[i];
ChildNode := FindChildNodeByKey(RootNode, ChildKeys[i]);
Assert(ChildNode <> Nil);
ChildNode.Checked := True;
end;
CDS1.Next;
end;
finally
CDS1.EnableControls;
end;
finally
ChildKeys.Free;
end;
finally
cxTreeList1.EndUpdate;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
CDS1.CreateDataSet;
ClearChecks;
end;
procedure TForm1.btnClearClick(Sender: TObject);
begin
ClearChecks;
end;
procedure TForm1.btnLoadClick(Sender: TObject);
begin
LoadTreeState;
end;
procedure TForm1.btnSaveClick(Sender: TObject);
begin
SaveTreeState;
end;
end.
来源:https://stackoverflow.com/questions/58991592/delphi-cxtreelist-looping-through-nodes