5

私はDelphi2010を使用しており、VirtualStringTreeを使用して頭を包み込もうとしています。

私はそれをオブジェクトで動作させることを試みてきましたが、soft-gems.netWebサイトで見つけたPhilippFrenzelのVirtualTreeViewチュートリアルに従うまで運がありませんでした。私がこれまでに思いついたものは機能しますが、サブノード(つまり子ノード)を正しく処理しているとは思いません。

私が機能することができた唯一のことは、各子に対してオブジェクト全体を再度リンクし、必要なフィールドを表示することです-しかし、それはとても間違っていると感じます。

提案/フィードバックは大歓迎です。


VirtualStringTreeに接続しようとしているオブジェクトのリストがあります。ここでは、フィールドの1つが親のラベルとして機能し、残りのフィールドが子ノードとして表示される、このようなことを実現しようとしています。

  • ロバートレーン
    • 35
    • ロサンゼルス
    • ブルネット
  • ジェーン・ドウ
    • 女性
    • 19
    • デンバー
    • 赤毛

これが私のクラスの設定方法です。

type
  PTreeData = ^TTreeData;
  TTreeData = record
    FObject : TObject;
  end;

  TCustomerNode = class(TObject)
  private
    fName: string;
    fSex: string;
    fAge: integer;
    fHair: string;
    //...
  public
    property Name: string read fName write fName;
    //...
  end;

オブジェクトを入力したら、以下で説明するTListに基づく別のクラス(CustomerObjectList)にオブジェクトを追加します。

ここで、VirtualStringTreeをオブジェクトリストに接続します

procedure TfrmMain.btnLoadDataClick(Sender: TObject);
var
  i, j : integer;
  CustomerDataObject: TCustomerNode;
  RootXNode, XNode: PVirtualNode;
  Data: PTreeData;
begin
  vstree.NodeDataSize := SizeOf( TTreeData );

  vstree.BeginUpdate;
  for i := 0 to CustomerObjectList.Count - 1 do
  begin
    CustomerDataObject := CustomerObjectList[i];

    //load data for parent node
    RootXNode := vstree.AddChild(nil);
    Data  := vstree.GetNodeData(RootXNode);
    Data^.FObject:= PINodeSource;

    //now add children for rest of fields
    //Isn't there a better way to do this?
    for j := 1 to NUMBERofFIELDS -1 do  //first field is label for parent so -1
    begin
      XNode := vstree.AddChild(RootXNode);
      Data  := vstree.GetNodeData(XNode);
      Data^.FObject:= PINodeSource;
    end;

  end;
  vstree.EndUpdate; 
end;    

procedure TfrmMain.vstreeGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
 Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
var
  Data : PTreeData;
begin
  Data := vstObjects.GetNodeData(Node);
  ////if Node.ChildCount  = 0 then //edit - oops typo!
  if Node.ChildCount  > 0 then
  begin
    CellText := TCustomerNode(Data.FObject).Name;
    exit;
  end;

  //handle childnodes
  case Node.Index of
    0:  CellText := TCustomerNode(Data.FObject).Sex;
    1:  CellText := IntToStr(TCustomerNode(Data.FObject).Age);
    2:  CellText := TCustomerNode(Data.FObject).Hair;
    3:  CellText := TCustomerNode(Data.FObject).City;
  end;  
end;
4

2 に答える 2

7

すべてのデータをツリーにロードする必要はありません。ツリーの「仮想性」を利用できます。これが私がそれを行う方法です。

ツリーの RootNodeCount を CustomerObjectList のレコード数に設定します。

vstree.RootNodeCount := CustomerObjectList.Count;

次に、OnInitChildren イベントで、レベル 0 ノードの子の数を、表示するプロパティの数に設定します。

procedure TfrmMain.vstreeInitNode(Sender: TBaseVirtualTree; ParentNode, Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
begin
  if Sender.GetNodeLevel(Node) = 0 then
  begin
    Sender.ChildCount[Node] := 4;

    // Comment this out if you don't want the nodes to be initially expanded
    Sender.Expanded[Node] := TRUE;
  end;
end;

ここで、OnGetText イベントで正しいデータを取得するだけです。

procedure TfrmMain.vstreeGetText(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
  var CellText: string);
begin
  if Column <= 0 then
  begin
    if Sender.GetNodeLevel(Node) = 0 then
      CellText := CustomerObjectList[Node.Index].Name else
    if Sender.GetNodeLevel(Node) = 1 then
    begin
      case Node.Index of
        0: CellText := CustomerObjectList[Parent.Node.Index].Sex;
        1: CellText := CustomerObjectList[Parent.Node.Index].Age;
        2: CellText := CustomerObjectList[Parent.Node.Index].Hair;
        3: CellText := CustomerObjectList[Parent.Node.Index].City;
      end; // of case
     end;
end;

念のため、さらに範囲チェックを追加することをお勧めします。

お役に立てれば。

于 2011-11-05T08:02:59.543 に答える