Delphi cxtreelist looping through nodes

心已入冬 提交于 2019-12-11 04:52:05

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!