如何在InitNode事件中将数据分配给VirtualStringTree的节点

时间:2014-10-29 14:46:21

标签: delphi virtualtreeview tvirtualstringtree

我不确定如何将数据分配给VirtualStringTree中的节点。我需要在树控件的InitNode事件中将指向记录对象的指针分配给Node的Data属性。但是我得到了'需要指针类型'的编译时错误。

type
  TDiagData = record
    DiagID: Integer;
    DiagName: String;
    Selected: Byte;
  end;

  PDiagData = ^TDiagData;

var
  FDiagDataList: TObjectList;
  c: Integer; // used as an iterator for the list // incremented in vst1InitNode



procedure Btn1Click;
var
  DiagData : PDiagData;
begin

  try
    FDiagDataList := TObjectList.Create; // TODO: Move this to form constructor

    for c := 1 to 10 do
    begin
      New(DiagData);

      DiagData.DiagID := c;
      DiagData.DiagName := Format('Diag# %d', [c]);

      FDiagDataList.Add(DiagData);
    end;

    c := 0;

    vst1.NodeDataSize := SizeOf(TDiagData);
    vst1.RootNodeCount := 10; // test

  finally
    //  FDiagDataList.Free;   //TODO: Move this to form destructor
  end
end;

procedure vst1InitNode(Sender: TBaseVirtualTree; ParentNode, Node: PVirtualNode;
  var InitialStates: TVirtualNodeInitStates);
var
  DiagData: PDiagData;
begin

  DiagData = TDiagData(FDiagDataList.Items[c]); // FDiagDataList is a TObjectlist

  Node.Data^ := DiagData; // <--- this is not working ..
  // The error is: Pointer type required.

  Inc(c);
end;

我需要在InitNode事件中将数据分配给节点,但不确定如何分配它。

1 个答案:

答案 0 :(得分:2)

不要直接读或写Node.Data。您所需的数据一定必须完全位于该字段的地址。 (树控件有一种机制,允许后代为自己保留其他数据。)而是调用Sender.GetNodeData

var
  NodeData: PDiagData;
begin
  NodeData := Sender.GetNodeData(Node);
  NodeData^ := TDiagData(FDiagDataList.Items[c]);
end;

您的代码失败,因为Node.Data的类型为record;你不能用^取消引用它。在简单的情况下,GetNodeData返回的值将等于该字段的地址(即GetNodeData(Node) = @Node.Data)。但不要假设所有案例都很简单。正如我所说,树控制后代可以保留自己的数据空间,因此您可以使用您无法控制的代码共享该空间,并且它已经完成了到树控件来管理哪个数据空间是你的。始终致电GetNodeData


此外,您对数据类型感到困惑。您说FDiagDataListTObjectList,但您清楚地存储了不是<{1}}的后代的内容。如果您不使用对象,请不要使用TObject。如果您在2009年之前使用的是Delphi版本,请使用TObjectList并将指针存储到TList

TDiagData

如果您正在使用Delphi 2009或更高版本,请使用NodeData^ := PDiagData(FDiagDataList[c])^; ,然后摆脱类型转换:

TList<TDiagData>

无论哪种方式,如果每个事件处理程序以相同的方式启动,并且调用NodeData^ := FDiagDataList[c]; 来获取类型安全指针,您可能会发现更容易管理的事情到当前节点的数据。