VirtualTreeview节点,将它们传递给另一种形式?

时间:2011-02-04 20:13:10

标签: delphi virtualtreeview

我的应用程序将通过虚拟节点循环并检查其数据。我使用另一个表单来执行此操作比包含VirtualStringTree的表单。 (我得到了我的理由;))

我的问题是:如何将这些节点+他们的数据传递给我的其他形式的函数,然后能够循环通过节点(我知道如何循环,我只需要节点可用于我的另一种形式)。

另外,请注意,一旦显示Processing表单,就会销毁包含VirtualStringTree的表单!

我怎么能这样做?我正在考虑创建一个动态的VirtualStringTree,并以某种方式将节点从一棵树传递到另一棵树,但我会先问这里是否有更好的解决方案。 :)

谢谢,杰夫。

1 个答案:

答案 0 :(得分:13)

I've mentioned before你做错了,现在你会明白为什么。

您正在使用树形控件来存储数据。这意味着显示数据。您应该有一个单独的数据结构,其作业将存储您的数据。它可能是tree,但不是树控件。这是您为处理表单提供的树数据结构,因为它不需要显示节点。

当您想要显示数据时,可以找到树的第一级中有多少个节点,然后将树控件的RootNodeCount属性设置为该数字。控件将分配那么多节点 - 不要调用AddNewNode进行批量操作,比如填充控件。当树要在屏幕上显示之前未显示的节点时,它将触发OnInitNode事件处理程序。这是您初始化节点并将其与数据结构中的值相关联的位置。树控件将告诉您它正在初始化的节点 - 通过PVirtualNode指针和通过索引来告诉它相对于其父节点的哪个节点。初始化节点时,告诉树该节点是否有子节点。您不需要告诉它还有多少孩子;如果控制人想知道,它会问你另一个事件。

既然您已将数据与数据的演示文稿分开,那么您再也不必担心演示者的生命周期与数据的生命周期不同。处理表单可以处理数据,而不考虑树视图控件是否仍然存在,因为树视图控件从不拥有数据。

另见:


你说你只有一级节点。没关系。只有一个级别的树通常称为列表。您可以使用几种方法来跟踪列表。最简单的是数组。您也可以使用TList,也可以构建自己的链接列表。这个例子将使用一个数组,因为我想专注于树控件。

假设每个节点的数据由记录TData表示,所以你有一个数组:

var
  Data: array of TData;

在您使用任何来源加载数组后,您已准备好填充树控件。这就像两行代码一样简单(如果控件开始为空,则为一行):

Tree.ResetNode(nil); // remove all existing nodes from tree
Tree.RootNodeCount := Length(Data); // allocate new nodes for all data

当树确定它需要有关这些节点中的任何节点的更多信息时,它将从触发OnInitNode事件开始。您不需要为该事件做很多事情,因为节点的Index字段足以让我们找到与任何给定树节点对应的TData记录。

procedure TJeffForm.TreeInitNode(Sender: TBaseVirtualTree;
    ParentNode, Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
begin
  Assert(Node.Index < Length(Data), 'More nodes than data elements!?');
  InitialStates := []; // If the node had children, or if it should be
                       // initially disabled, you'd set that here.
end;

当树想要自己绘制时,它会通过触发OnGetText事件询问您为每个可见节点显示的文本。节点的Index字段告诉您它相对于其父项的项目。 (由于您只有一个列表,该索引对应于列表中的索引。)

procedure TJeffForm.TreeGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
    Column: TColumnIndex; TextType: TVSTTextType; var CellText: UnicodeString);
begin
  if TextType = ttStatic then
    exit;
  case Column of
    NoColumn,
    0: CellText := Data[Node.Index].Name;
    1: CellText := 'Second column';
    else
      Assert(False, 'Requested text for unexpected column');
  end;
end;

上面我假设TData有一个名为Name的字符串字段,这就是我们应该在主列中显示的内容。如果树要求提供超过第二列的任何文本的文本,我们将得到断言失败,表明我们尚未准备好发布该产品。

注意我们如何使用节点索引来查看完全独立的数组数据结构。我们可以完全破坏树控件,数据仍然存在。当您的处理表单需要处理数据时,请为其指定Data数组,而不是树控件。