VirtualTreeview节点,将它们传递给另一种形式? [英] VirtualTreeview Nodes, pass them to another form?

查看:109
本文介绍了VirtualTreeview节点,将它们传递给另一种形式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序将遍历虚拟节点并检查其数据.我正在使用另一种形式来执行此操作,而不是包含VirtualStringTree的形式. (我有我的理由;))

My application will be looping thru the Virtual Nodes and check their data. I am using another form to do this than the form containing the VirtualStringTree. (I got my reasons ;) )

我的问题是:如何将那些节点及其数据传递给其他形式的函数,然后它将能够通过这些节点循环(我知道如何循环,我只需要在我的其他表格).

My question is: How can I pass those nodes + their data to a function in my other form, which will then be able to loop thru the nodes (I know how to loop, I just need the nodes to be available in my other form).

另外,请注意,一旦显示正在处理中的表单,包含VirtualStringTree的表单就会被破坏!

Also, please note that the form that contains the VirtualStringTree is destroyed once the Processing form is being shown!

我该怎么做?我正在考虑创建一个动态的VirtualStringTree,并以某种方式将节点从一棵树传递到另一棵树,但是我首先要在这里寻求更好的解决方案. :)

How could I do that? I am thinking about creating a dynamic VirtualStringTree, and somehow pass the nodes from 1 tree to the other, but I would ask here first for any better solutions. :)

谢谢杰夫.

推荐答案

我之前已经提到过表示您做错了事,现在您将了解原因.

I've mentioned before that you're doing things wrong, and now you'll see why.

您正在使用树控件存储数据.它用于显示数据.您应该有一个单独的数据结构,其 only 任务是存储数据.它可能是一棵,而不是一棵树 control .您将这种树数据结构提供给处理表单,因为它不需要显示节点.

You're using the tree control to store your data. It's meant for displaying the data. You should have a separate data structure whose only job is to store your data. It will probably be a tree, but not a tree control. It's this tree data structure that you'd give to the processing form since it has no need for displaying nodes.

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

When you want to display your data, you find out how many nodes there are in the first level of your tree, and then you set your tree control's RootNodeCount property to that number. The control will allocate that many nodes — don't call AddNewNode for bulk operations like populating the control. When the tree is going to display a node on the screen that it hasn't displayed before, it will fire the OnInitNode event handler. That's where you initialize the node and associate it with a value in your data structure. The tree control will tell you which node it's initializing — both via a PVirtualNode pointer and via an index that tells which node it is, relative to its parent. When you're initializing the node, you tell the tree whether the node has any children. You don't need to tell it how many children yet; if the control wants to know, it will ask you with another event.

现在,您已经将数据与仅数据的表示分开了,您不再需要担心演示者的生命周期不同于数据的生命周期.该处理表单可以处理数据,而无需考虑树视图控件是否仍然存在,因为树视图控件从一开始就从未拥有过数据.

Now that you've separated your data from the mere presentation of your data, you no longer have to worry about the lifetime of the presenter differing from the lifetime of your data. The processing form can process the data without regard for whether the tree-view control still exists because the tree-view control never owned the data in the first place.

另请参阅:

您已经说过您只有一个级别的节点.没关系.一棵只有一个级别的树通常称为 list .您可以使用几件事来跟踪列表.最简单的是 array .您也可以使用TList,也可以构建自己的链接列表.本示例将使用数组,因为我想专注于树控件.

You've said you only have one level of nodes. That's OK. A tree with only one level is more commonly known as a list. There are several things you can use to keep track of a list. The simplest is an array. You can also use a TList, or you can build your own linked list. This example will use an array because I want to focus on the tree control.

让我们假设每个节点的数据由一条记录TData表示,因此您有一个数组:

Let's suppose the data for each node is represented by a record, TData, so you have an array of those:

var
  Data: array of TData;

在从阵列中加载信息后,无论您使用什么来源,都可以填充树控件.就像两行代码一样容易(如果控件开始为空,则只需一行):

After you've loaded the array with information, from whatever source you have, you're ready to populate the tree control. That's as easy as two lines of code (one, if the control started out empty):

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

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

As the tree determines that it needs more information about any of those nodes, it will start by triggering the OnInitNode event. There's no much you need to do for that event since the node's Index field will be sufficient for us to find the TData record that corresponds to any given tree node.

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字段告诉您相对于其父项的项. (由于您只有一个列表,因此该索引对应于列表中的索引.)

When the tree wants to paint itself, it will ask you what text to display for each visible node by triggering the OnGetText event. The Index field of the node tells you which item it is, relative to its parent. (Since you just have a list, that index corresponds to the index in your list.)

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的字符串字段,这就是我们应该在主列中显示的内容.如果树要求在第二列之后输入任何文本,我们将得到断言失败,表明我们尚未准备好发布产品.

Above I've assumed that TData has a string field named Name and that that's what we should display in the main column. If the tree asks for text for anything past the second column, we'll get an assertion failure, signalling that we're not ready to release the product yet.

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

Notice how we use the node index to look into the entirely separate array data structure. We could destroy the tree control entirely, and the data would still exist. When your processing form needs to process data, give it the Data array, not the tree control.

这篇关于VirtualTreeview节点,将它们传递给另一种形式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆