Sto usando una TVirtualStringTree per archiviare i puntatori ai record.VirtualStringTree - Puntatore memorizzato <> Puntatore recuperato! Il mio approccio al codice è sbagliato?
Originariamente c'è un TList che contiene l'elenco dei record.
Sto utilizzando l'evento OnInitNode per scorrere il TList e assegnare i dati di ogni record ai nodi dell'albero.
Tuttavia, quando si recuperano i dati associati a un nodo nel gestore eventi OnNewText, il puntatore restituito ha un indirizzo diverso da quello memorizzato in origine nell'albero.
Inoltre, è possibile vedere attraverso il debug che il puntatore (ai dati del record) recuperato dal nodo è non lo uguale a quello memorizzato originariamente nel nodo. Devo salvare i dati modificati in un database e devo fare riferimento al record con i dati modificati. Dovrebbe essere semplice come riferimento al puntatore, ma il problema è che il puntatore non è lo stesso.
Non sono sicuro di cosa sto sbagliando e spero che qualcuno possa aiutarmi a risolverlo.
Grazie in anticipo.
Ecco il mio codice:
struttura dei dati e dichiarazioni:
TTherapData = record
TherapID: Integer;
TherapName: String[120];
TherapInstr: String[120];
Selected_DB: Byte;
Selected: Byte;
end;
PTherapData = ^TTherapData;
FTherapDataList: TList<PTherapData>;
FTherapDataListAsg_Iter: Integer;
vstRxList_Asg: TVirtualStringTree;
Caricamento dei dati nel TList, e poi contro l'albero:
procedure TfmPatient_Conslt.LoadTherapList(const ADBLoad: Boolean = False);
var
TherapData: PTherapData;
d, x: Integer;
begin
datamod.uspLKTHERAP_S.First;
while not datamod.uspLKTHERAP_S.Eof do
begin
New(TherapData);
TherapData^.TherapID := datamod.uspLKTHERAP_SROW_ID.AsInteger;
TherapData^.TherapName := datamod.uspLKTHERAP_SIMPRTHERAP.AsString;
TherapData^.TherapInstr := EmptyStr;
TherapData^.Selected := 0;
TherapData^.Selected_DB := 0;
FTherapDataList.Add(TherapData);
datamod.uspLKTHERAP_S.Next;
end;
datamod.uspCONSLT_RX_S.First;
while not datamod.uspCONSLT_RX_S.Eof do
begin
d := datamod.uspCONSLT_RX_SRX_ID.AsInteger;
TherapData := FTherapDataList[TherapDataList_GetIndexOfID(d)];
TherapData^.TherapInstr := datamod.uspCONSLT_RX_SRX_INSTRUCTION.AsString;
TherapData^.Selected := 1;
TherapData^.Selected_DB := 1;
datamod.uspCONSLT_RX_S.Next;
end;
x := TherapDataList_CountSelectedItems;
FTherapDataListAsg_Iter := 0;
vstRxList_Asg.NodeDataSize := SizeOf(TTherapData);
vstRxList_Asg.RootNodeCount := 0;
vstRxList_Asg.RootNodeCount := x;
end;
procedure TfmPatient_Conslt.vstRxList_AsgInitNode(Sender: TBaseVirtualTree; ParentNode, Node: PVirtualNode;
var InitialStates: TVirtualNodeInitStates);
var
TherapData: PTherapData;
begin
TherapData := Sender.GetNodeData(Node);
while (FTherapDataList[FTherapDataListAsg_Iter]^.Selected <> 1) do
Inc(FTherapDataListAsg_Iter);
TherapData^.TherapID := FTherapDataList[FTherapDataListAsg_Iter]^.TherapID;
TherapData^.TherapName := FTherapDataList[FTherapDataListAsg_Iter]^.TherapName;
TherapData^.TherapInstr := FTherapDataList[FTherapDataListAsg_Iter]^.TherapInstr;
{ TherapData := FTherapDataList[FTherapDataListAsg_Iter]; } //
{ TherapData^ := FTherapDataList[FTherapDataListAsg_Iter]^; } //
Inc(FTherapDataListAsg_Iter);
end;
procedure TfmPatient_Conslt.vstRxList_AsgGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex;
TextType: TVSTTextType; var CellText: string);
var
TherapData: PTherapData;
begin
TherapData := Sender.GetNodeData(Node);
if Assigned(TherapData) then
if (Column = 0) then
CellText := TherapData^.TherapName
else if (Column = 1) then
CellText := TherapData^.TherapInstr;
end;
procedure TfmPatient_Conslt.vstRxList_AsgEditing(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex;
var Allowed: Boolean);
begin
Allowed := (Column = 1);
end;
il recupero dei dati. Ho notato che il problema qui:
procedure TfmPatient_Conslt.vstRxList_AsgNewText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex;
NewText: string);
var
TherapData: PTherapData;
begin
if (Column = 1) then
begin
TherapData := Sender.GetNodeData(Node);
if Assigned(TherapData) then // <---- There is a debug breakpoint here
// and the watch window screen-shot
// is taken here
TherapData^.TherapInstr := NewText;
// Showmessage(Format('%p', [TherapData])); // <---- The pointer value is not the same
// as that originally stored !
end;
end;
Questo è dove ho salvare i dati della lista al database, e la ragione per cui ho bisogno l'albero per modificare le dati originali e non una copia:
procedure TfmPatient_Conslt.SaveRxListToDB;
var
TherapData: PTherapData;
begin
for TherapData in FTherapDataList do
begin
if (TherapData^.Selected = 1) and (TherapData^.Selected_DB = 0) then
begin
// Add new entries to DB
// :ROW_ID, :CONSLT_ID, :RX_ID, :RX_INSTRUCTION
datamod.uspCONSLT_RX_I.ParamByName('ROW_ID').AsInteger := 0;
datamod.uspCONSLT_RX_I.ParamByName('CONSLT_ID').AsInteger := FConsultationID;
datamod.uspCONSLT_RX_I.ParamByName('RX_ID').AsInteger := TherapData^.TherapID;
datamod.uspCONSLT_RX_I.ParamByName('RX_INSTRUCTION').AsString := TherapData^.TherapInstr;
datamod.uspCONSLT_RX_I.PrepareSQL(False);
datamod.uspCONSLT_RX_I.ExecProc;
TherapData^.Selected_DB := 1;
end
else if (TherapData^.Selected = 1) and (TherapData^.Selected_DB = 1) then
begin
// Update existing DB entries
// :CONSLT_ID, :RX_ID, :RX_INSTRUCTION
datamod.uspCONSLT_RX_U.ParamByName('CONSLT_ID').AsInteger := FConsultationID;
datamod.uspCONSLT_RX_U.ParamByName('RX_ID').AsInteger := TherapData^.TherapID;
datamod.uspCONSLT_RX_U.ParamByName('RX_INSTRUCTION').AsString := TherapData^.TherapInstr;
datamod.uspCONSLT_RX_U.PrepareSQL(False);
datamod.uspCONSLT_RX_U.ExecProc;
end
else if (TherapData^.Selected = 0) and (TherapData^.Selected_DB = 1) then
begin
// Delete removed entries from DB
// :CONSLT_ID, :RX_ID
datamod.uspCONSLT_RX_D.ParamByName('CONSLT_ID').AsInteger := FConsultationID;
datamod.uspCONSLT_RX_D.ParamByName('RX_ID').AsInteger := TherapData^.TherapID;
datamod.uspCONSLT_RX_D.PrepareSQL(False);
datamod.uspCONSLT_RX_D.ExecProc;
TherapData^.Selected_DB := 0;
end;
end;
end;
Ecco uno screenshot della finestra dalla Debug-> selezione:
Oh, finalmente abbiamo ottenuto ['a c'] (http://stackoverflow.com/questions/26633391/how-to-assign-data-to-node-of-virtualstringtree-in-initnode-event/26636017# comment41883233_26636017) :) – TLama
@TLama :) Sì. Che viaggio lungo e strano è stato .. –