1

我有一个显示在 VirtualStringTree 中的数据层次结构。我在我的应用程序中多次使用此层次结构,并对树的绘制/显示方式稍作修改。我的方法目前使用 AddChild() 过程来添加节点,因此当应用程序运行时我有多个数据副本。

我现在想合并这些树并拥有一个指向实际数据的“主”树,然后让“从”树指向相同的数据。

我有点不确定是否/如何实现这一点。我想我可以简单地加载主树并用指向我保存数据的位置的指针填充它的 NodeData,然后对于所有从树,只需将相同的指针存储在它们的节点数据中。

但是我运气不好。

我当前的代码如下所示:

//Initialize the NodeDataSize
procedure TForm1.FormCreate(Sender: TObject);
begin
     TreeMasterComponents.NodeDataSize := SizeOf(rMasterComponent);
     VST.NodeDataSize := SizeOf(Pointer);
end;

将主树复制到从树的过程

procedure TForm1.LoadSlaveTree(ATree: TVirtualStringTree);
var Node : PVirtualNode;

procedure RecursiveCopy(SrcPNode,SrcTNode : PVirtualNode; ATree : TVirtualStringTree);
var SrcNode, TargetNode : PVirtualNode;
SrcData : PMasterComponent;
begin
     SrcNode := TreeMasterComponents.GetFirstChild(SrcPNode);
     while Assigned(SrcNode) do
     begin
          SrcData := TreeMasterComponents.GetNodeData(SrcNode);
          TargetNode := ATree.AddChild(SrcTNode,SrcData);
          RecursiveCopy(SrcNode,TargetNode,ATree);
          SrcNode := SrcNode.NextSibling;
     end;
end;

begin
     ATree.BeginUpdate;
     ATree.Clear;
     Node := TreeMasterComponents.GetFirst(true);
     while Assigned(Node) do
     begin
         RecursiveCopy(Node,nil,ATree);
         Node := Node.NextSibling;
     end;
     ATree.EndUpdate;
end;

从树获取CellText的过程

procedure TForm1.SlaveGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
var Data : PMasterComponent;
begin
     Data := Sender.GetNodeData(Node);
     Case column of
     0:CellText := Data^.ComponentCode;
     1:CellText := Data^.FullLocation;
     end;
end;

目前,节点已添加到正确的层次结构中,但是从属树没有出现任何文本。任何帮助,将不胜感激。

4

2 回答 2

2

我不知道为什么您的奴隶树中没有文本,但我想建议以下几点。

可能更容易使用树和代码创建一个框架,并在表单上重用该框架。树的每个实例都将简单地加载相同的数据(无需复制节点)。

通过为框架/树的特定实例编写新的事件处理程序,可以通过可视化表单继承来实现轻微的修改。如果需要,您还可以从框架继承,创建一个新类。

于 2011-10-25T06:47:09.257 回答
2

好的,所以我相信我找到了解决方案:

诀窍是创建一个新记录来存储指向原始数据的指针:

type PRefMasterComponent = ^RefMasterComponent;
  RefMasterComponent = packed record
     PMCData : PMasterComponent;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
     TreeMasterComponents.NodeDataSize := SizeOf(rMasterComponent);
     VST.NodeDataSize := SizeOf(RefMasterComponent);
end;

现在复制代码如下所示:

procedure TForm1.LoadTree(ATree: TVirtualStringTree);
var Node,TargetNode : PVirtualNode;
SrcData : PMasterComponent;
Data : PRefMasterComponent;

procedure RecursiveCopy(SrcPNode, TargetPNode : PVirtualNode; ATree : TVirtualStringTree);
var Node, TargetNode : PVirtualNode;
SrcData : PMasterComponent;
Data : PRefMasterComponent;
begin
     Node := TreeMasterComponents.GetFirstChild(SrcPNode);
     while Assigned(Node) do
     begin
          SrcData := TreeMasterComponents.GetNodeData(Node);
          TargetNode := ATree.AddChild(TargetPNode);
          Data := ATree.GetNodeData(TargetNode);
          Data.PMCData := SrcData;
          RecursiveCopy(Node,TargetNode,ATree);
          Node := Node.NextSibling;
     end;
end;

begin
     ATree.BeginUpdate;
     ATree.Clear;
     Node := TreeMasterComponents.GetFirst(true);
     while Assigned(Node) do
     begin
          SrcData := TreeMasterComponents.GetNodeData(Node);
          TargetNode := ATree.AddChild(nil);
          Data := ATree.GetNodeData(TargetNode);
          Data.PMCData := SrcData;
          RecursiveCopy(Node,TargetNode,ATree);
          Node := Node.NextSibling;
     end;
     ATree.EndUpdate;
end;

和 OnGetText:

procedure TForm1.vstGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
var Data : PRefMasterComponent;
RefData : PMasterComponent;
begin
     Data := Sender.GetNodeData(Node);
     RefData := Data.PMCData;
     Case column of
     0:CellText := RefData.ComponentCode;
     1:CellText := RefData.FullLocation;
     end;
end;

现在,如果我更改一棵树中的数据,我所要做的就是调用 VST.Invalidate,并且更改会反映在另一棵树中。

于 2011-10-25T06:56:00.697 回答