Синхронизируйте несколько VirtualStringTrees, используя 1 копию данных - PullRequest
1 голос
/ 25 октября 2011

У меня есть иерархия данных, которая отображается в VirtualStringTree.Я использую эту иерархию несколько раз в своем приложении с небольшими изменениями в способе отображения / отображения дерева.Мой метод в настоящее время использует процедуру AddChild () для добавления узлов и d, поэтому у меня есть несколько копий данных при запуске приложения.

Теперь я хотел бы объединить эти деревья и получить «главное» дерево.который указывает на фактические данные, но затем «подчиненные» деревья указывают на те же данные.

Я немного не уверен в том, можно ли добиться этого.Я думаю, я мог бы просто загрузить главное дерево и заполнить его 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;

Процедура для подчиненного дерева в getCellText

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;

В данный момент узлы добавляются в правильной иерархии, однако текст для подчиненных деревьев не отображается.Любая помощь будет оценена.

Ответы [ 2 ]

2 голосов
/ 25 октября 2011

Хорошо, я верю, что нашел решение:

Хитрость заключалась в том, чтобы создать новую запись для хранения указателя на исходные данные:

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, и изменения будут отражены в другом дереве.

2 голосов
/ 25 октября 2011

Я не знаю, почему на ваших подчиненных деревьях нет текста, но я бы хотел посоветовать следующее.

Вероятно, проще было бы создать фрейм с деревом и кодом и повторно использовать фрейм в ваших формах. Каждый экземпляр дерева будет просто загружать одни и те же данные (копирование узлов не требуется).

Небольшие изменения могут быть достигнуты путем визуального наследования форм путем написания новых обработчиков событий для конкретного экземпляра фрейма / дерева. Вы также можете наследовать от фрейма, создавая новый класс, если это необходимо.

...