Я уже говорил , что вы делаете что-то не так, и теперь вы поймете, почему.
Вы используете древовидный элемент управления для хранения ваших данных. Он предназначен для отображения данных. У вас должна быть отдельная структура данных, задача которой only - хранить ваши данные. Вероятно, это будет дерево , но не дерево control . Именно эту древовидную структуру данных вы дадите форме обработки, поскольку для нее не нужно отображать узлы.
Когда вы хотите отобразить свои данные, вы узнаете, сколько узлов имеется на первом уровне вашего дерева, а затем вы задаете для свойства 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
, а не элемент управления tree.