Antes de empezar, entre los dos componentes te recomiendo que utilices el VirtualTreeView. TJvDBTreeView es poco efeciente y muy poco dinámico.
Para trabajar con el VirtualTreeView [VTV] debes estar muy familiarizado con los punteros. Si tienes un buen entendimiento de los punteros se te hará mucho más fácil trabajar con el VTV.
Lo primero que debes de definir es el tipo de datos de cada Nodo. El tipo de datos debe ser un puntero a un registro. El registro puede contener las propiedades que quieras.
Para explicartelo haré un mini tutorial. Utilizaré dos tablas virtuales. Una llamada clientes y otra llamada contactos. Cada cliente será represetando por un nodo en el VTV. Su respectivos contactos serán representados por subnodos.
Empezaremos por definir el registro de datos que utilizaremos para los nodos:
Código Delphi
[-]
type
TVTVNodeType = (ntClient, ntContact);
TMyNodeData = record
NodeType: TVTVNodeType; ID: Variant; Name: String; HasContacts: Boolean; end;
PMyNodeData = ^TMyNodeData;
Luego, escribiré un par de funciones que me serviraran para luego ubicar nodos en el árbol.
Código Delphi
[-]
function get_node_of(Tree: TBaseVirtualTree,
NodeType: TVTVNodeType,
ID: Variant,
ParentNode: PVirtualNode = nil);
var
NodeData: PMyNodeData;
CurrentNode: PVirtualNode;
begin
result := nil;
if ParentNode = nil then
ParentNode := Tree.RootNode;
CurrentNode = Tree.GetFirstChild(ParentNode)
with Tree do
while (CurrentNode <> nil)
begin
if not assigned(GetNodeData(CurrentNode)) then
begin
CurrentNode := Tree.GetNext(CurrentNode);
continue;
end;
NodeData = GetNodeData(CurrentNode);
if (NodeData.NodeType = NodeType) and (NodeData.ID = ID) then
begin
result := CurrentNode;
break;
end
else
CurrentNode := Tree.GetNext(CurrentNode);
end;
end;
Ahora haremos la primera etapa. Mostrar todos los registros de clientes en el evento OnShow del formulario. Crearemos un nodo para cada registro de cliente.
Código Delphi
[-]
procedure TForm1.OnShow(Sender: TObject);
var
I: Integer;
NewNodeData: PMyNodeData;
NewNode: PVirtualNode;
begin
VTView.NodeDataSize := SizeOf(TMyNodeData);
for I := 0 to Dataset.RecorCount -1 do
begin
NewNode := VTView.AddChild(nil, NewNodeData);
NewNodeData.NodeType := ntClient;
NewNodeData.ID := Dataset.Records[i].FieldByName('id').Value;
NewNodeData.Name := Dataset.Records[i].FieldByName('name').Value;
NewNodeData.HasContacts := Dataset.Records[i].FieldByName('has_contacts').Value;
if NewNodeData.HasContacts then
Include(NewNode.States, vsHasChildren);
end;
end;
Ya hemos agregado los nodos. VirtualTreeView te permite crear nodos y árboles muy elaborados. O sencillos si así lo prefieres. Para este ejemplo usaremos nodos sencillos. Sin mucho adorno. VTV se encargará de pintarlos y no nosotros. Pero VTV necesita saber que cuál es el texto que mostrará en cada nodo. Así que nos lo debe preguntar en el evento "OnGetText". En este evento nuestro código devolverá la propiedad "name" de nodo.
Código Delphi
[-]
procedure TForm1.VTVIewGetText(Sender: TBaseVirtualTree;
Node: PVirtualNode;
Column: Integer; TextType: TVSTTextType;
var Text: WideString);
var
NodeData: PMyNodeData
begin
NodeData := Sender.GetNodeData(Node);
if (NodeData <> nil)
Text := NodeData.Name
else
Text := '';
end;
Cuando el usuario expanda un Node de clientes que tiene contactos, debemos cargar desde la DB los registros de contactos. Esto lo haremos en el evento OnInitChildren.
Código Delphi
[-]
procedure TForm1.VTVIewInitChildren(Sender: TBaseVirtualTree;
Node: PVirtualNode;
var ChildCount: Cardinal);
var
I: Integer;
ClientNodeData, NewNodeData: PMyNodeData;
NewNode: PVirtualNode;
begin
ChildCount := 0;
ClientNodeData := Sender.GetNodeData(Node);
Dataset := Database.query('select * from contacts where client = ' + ClientNodeData.ID);
for I := 0 to Dataset.RecorCount -1 do
begin
NewNode := VTView.AddChild(Node, NewNodeData);
NewNodeData.NodeType := ntContact;
NewNodeData.ID := Dataset.Records[i].FieldByName('id').Value;
NewNodeData.Name := Dataset.Records[i].FieldByName('name').Value;
NewNodeData.HasContacts := False;
Inc(ChildCount);
end;
end;
A cómo ves todo se trata de manejar los punteros. Utilizado Drag-and-Drop, podríamos mover un contacto desde un cliente a otro cliente. Podríamos eliminar un registro de la DB cuando el usuario elimine un Nodo del árbol y muchas otras funcionalidades que están fuera del alcance de esta respuesta.
VirtualTreeView te ofrece una funcionalidad inigualable. Todo es cuestión de entender cómo opera el componente. VirtualTreeView es sólo como una base. Este componente hace preguntas para todo. Lo que tu código debe implementar son respuestas a esas preguntas. Preguntas que normalmente el componente te las hace en los eventos.
Saludos.