Delphi cxtreelist 遍历节点

Delphi cxtreelist looping through nodes

我有一个包含 3 列的 tcxTreeList,第一列设置为 属性 Node.CheckGroupType := ncgCheckGroup;,第2列是第一个根节点的Key,第3列是根节点下所有子节点的Key。 我怎样才能得到根节点的键,无论它是否被选中,以及所有被选中的子节点的键到 2 个变量中,以插入到数据库中,并从我们从数据库中获得的键中加载回项目

我添加项目的代码如下

 APNode := tv.Add;
 APNode.CheckGroupType := ncgCheckGroup;
 APNode.Values[0] := define;
 ApNode.Values[1] := dCode;

define - 包含 Created、Released、In-Active 等文本。所有 Root 节点 dcode - 包含每个根节点的键值,如 E、F、I、P、R

这就是我为每个根节点添加子节点的方式

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;

更新

dcode是一个字母,Definition是一个字符串,Dcode是定义中字符串的key,就像一个键值对Dcode是key,definition是value。 在树形列表中,根节点(如 Created、Released、In Active、Checked 和 Reactivated)在第 1 列中具有不同的键,而子节点值(如样品、开发、生产等)的键在第 3 列中。 只将Key值保存到DB中,根节点key无论是否Checked都直接保存。每个根节点键将被保存到不同的行,并且仅进入子节点。选中的节点键以逗号分隔保存到数据库中。 例如 。如果 Root node Created 和它下面的项目如 Sample , Development 被检查然后根节点键 E 是一列 [DEFCODE(Primarykey)] 和子节点键 M,E (DEFINITION) 用逗号分隔在另一列.

下面的代码显示了如何将根节点的 Checked 状态及其对应的状态保存到 TClientDataSet key 和一个以逗号分隔的子键列表,这些键使用 SaveTreeState 方法。

方法LoadTreeState清除ctTreeList中每个节点的Checked状态 然后从 CDS 重新加载保存的 Checked 状态。

要使用此代码,您需要将名为 CDS1 的 TClientDataSet 添加到您的项目中, 以及以通常方式连接起来的 TDataSource 和 TDBGrid。然后添加持久化 如代码所示,将字段添加到 CDS,编译并 运行.

我希望我已经理解你的 cxTreeList 是如何正确设置的,但如果没有,希望 代码应该非常简单,以适应您的实际操作。

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.