![]() |
TVirtualStringTree mit TObjectList
Hallo,
ich stehe grad etwas auf dem Schlauch: Ich möchte in einem TVirtualStringTree eine TObjectList anzeigen lassen die in etwa so aussieht: Zeitraum Spalte1 Spalte2 Spalte 3 01/2019 ==> Zeile1 Wert1 Wert2 Wert3 ==> Zeile2 Wert3 Wert4 Wert5 02/2019 ==> Zeile1 Wert6 Wert7 Wert8 ==> Zeile9 Wert10 Wert11 Wert12 Als Ergebnis kommt aber nur folgendes raus: Zeitraum Spalte1 Spalte2 Spalte 3 01/2019 ==> Zeile1 Wert1 Wert2 Wert3 ==> Zeile2 Wert3 Wert4 Wert5 02/2019 ==> Node Node Node Node ==> Node Node Node Node Was läuft das falsch? Wird das Object korrekt an ..GetText übergeben? Die Objectlist ist wie folgt definiert:
Code:
unit uMyTypes;
interface uses System.Classes,System.Generics.Collections; type TDetailClass = class private FWert1: String; FCaption: String; FWert2: String; FWert3: String; procedure SetCaption(const Value: String); procedure SetWert1(const Value: String); procedure SetWert2(const Value: String); procedure SetWert3(const Value: String); public property Caption: String read FCaption write SetCaption; property Wert1: String read FWert1 write SetWert1; property Wert2: String read FWert2 write SetWert2; property Wert3: String read FWert3 write SetWert3; end; TDataClass = class private FZeitraum: String; FDetail1: TDetailClass; FDetail2: TDetailClass; procedure SetZeitraum(const Value: String); procedure SetDetail1(const Value: TDetailClass); procedure SetDetail2(const Value: TDetailClass); public constructor Create; destructor destroy; property Zeitraum: String read FZeitraum write SetZeitraum; property Detail1: TDetailClass read FDetail1 write SetDetail1; property Detail2: TDetailClass read FDetail2 write SetDetail2; end; PDataClass = ^TDataClass; TDataLst = TObjectList<TDataClass>; implementation { TDetail } procedure TDetailClass.SetCaption(const Value: String); begin FCaption := Value; end; procedure TDetailClass.SetWert1(const Value: String); begin FWert1 := Value; end; procedure TDetailClass.SetWert2(const Value: String); begin FWert2 := Value; end; procedure TDetailClass.SetWert3(const Value: String); begin FWert3 := Value; end; { TData } constructor TDataClass.Create; begin FDetail1 := TDetailClass.Create; FDetail2 := TDetailClass.Create; end; destructor TDataClass.destroy; begin FDetail1.Free; FDetail2.Free; end; procedure TDataClass.SetDetail1(const Value: TDetailClass); begin FDetail1 := Value; end; procedure TDataClass.SetDetail2(const Value: TDetailClass); begin FDetail2 := Value; end; procedure TDataClass.SetZeitraum(const Value: String); begin FZeitraum := value; end; end.
Code:
procedure TForm5.Button10Click(Sender: TObject);
var vtc: TVirtualTreeColumn; vnHead: PVirtualNode; I: Integer; Data: TDataClass; begin vstSP.Header.Options := vstSP.Header.Options + [hoVisible]; vtc:= vstSP.Header.Columns.Add; vtc.Text:= 'Zeitraum'; vtc.Width := 150; vtc:= vstSP.Header.Columns.Add; vtc.Text:= 'Wert1'; vtc.Width := 100; vtc:= vstSP.Header.Columns.Add; vtc.Text:= 'Wert2'; vtc.Width := 100; vtc:= vstSP.Header.Columns.Add; vtc.Text:= 'Wert3'; vtc.Width := 100; vstSP.NodeDataSize:=SizeOf(TDataClass); vstSP.BeginUpdate; Data := TDataClass.Create; DataLst.Add(Data); Data.Zeitraum := '01/2019'; vnHead:= AddVSTStructureHeadClass(vstSP, nil, TDataClass(DataLst[0])); Data.Detail1.Caption:='Zeile1:'; Data.Detail1.Wert1 := 'Det1 - Wert1'; Data.Detail1.Wert2 := 'Det1 - Wert2'; Data.Detail1.Wert3 := 'Det1 - Wert3'; AddVSTStructureDetailClass(vstSP, vnHead, TDataClass(DataLst[0])); Data.Detail2.Caption:='Zeile2:'; Data.Detail2.Wert1 := 'Det2 - Wert1'; Data.Detail2.Wert2 := 'Det2 - Wert2'; Data.Detail2.Wert3 := 'Det2 - Wert3'; AddVSTStructureDetailClass(vstSP, vnHead, TDataClass(DataLst[0])); //Daten Fuellen2 Data := TDataClass.Create; DataLst.Add(Data); Data.Zeitraum := '02/2019'; vnHead:= AddVSTStructureHeadClass(vstSP, nil, TDataClass(DataLst[1])); Data.Detail1.Caption:='Zeile1:'; Data.Detail1.Wert1 := 'Det3 - Wert1'; Data.Detail1.Wert2 := 'Det3 - Wert2'; Data.Detail1.Wert3 := 'Det3 - Wert3'; AddVSTStructureDetailClass(vstSP, vnHead, TDataClass(DataLst[1])); Data.Detail2.Caption:='Zeile2:'; Data.Detail2.Wert1 := 'Det4 - Wert1'; Data.Detail2.Wert2 := 'Det4 - Wert2'; Data.Detail2.Wert3 := 'Det4 - Wert3'; AddVSTStructureDetailClass(vstSP, vnHead, TDataClass(DataLst[1])); vstSP.EndUpdate; vstSP.FullExpand; end; procedure TForm5.vstSPFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); var Data: PDataClass; begin Data := vstSP.GetNodeData(Node); if Assigned(Data) then begin Data := nil; end; end; procedure TForm5.vstSPGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string); var Data: PDataClass; begin Data := vstSP.GetNodeData(Node); if vstSP.GetNodeLevel(Node)=0 then //if Node.Index=0 then begin case Column of 0: CellText := Data.Zeitraum; 1: CellText := ''; 2: CellText := ''; 3: CellText := ''; end; end; if vstSP.GetNodeLevel(Node)=1 then //if Node.Index=1 then begin if vstSP.AbsoluteIndex(Node)=1 then begin case Column of 0: CellText := Data.Detail1.Caption; 1: CellText := Data.Detail1.Wert1; 2: CellText := Data.Detail1.Wert2; 3: CellText := Data.Detail1.Wert3; end; end; if vstSP.AbsoluteIndex(Node)=2 then // if Node.Index=2 then begin case Column of 0: CellText := Data.Detail2.Caption; 1: CellText := Data.Detail2.Wert1; 2: CellText := Data.Detail2.Wert2; 3: CellText := Data.Detail2.Wert3; end; end; end; end; |
AW: TVirtualStringTree mit TObjectList
Jeder Node des Vst sollte sein eigenes Data-Objekt haben.
Dann kannst du auch auf die Unterscheidung Detail1 und Detail2 verzeichten und hast einfach nur noch Detail. Im GetText kannst du dann bei NodeLevel = 1 einfach die Werte des Data-Objekts des jeweiligen Nodes ausgeben und musst nicht auf AbsoluteIndex prüfen. Das funktioniert hier nämlich nicht so, wie du dir das vorgestellt hast. Die beiden letzten Detailzeiten wären AbsoluteIndex 4 und 5. |
AW: TVirtualStringTree mit TObjectList
Vielen Dank für die Hilfe!
Zitat:
Aktuell hakt es nur beim zweiten Child. Wie bekomme ich da unterschiedliche Daten im zweiten Child angezeigt? Ich hatte bereits auf ein Detail zurückgebaut und AbsoluteIndex entfernt... |
AW: TVirtualStringTree mit TObjectList
Vllt hakt es noch am Verständnis, wie GetText aufgerufen wird? Nämlich für jeden Node extra. Es ist nicht notwendig, alle Nodes in der Funktion abzuarbeiten...
|
AW: TVirtualStringTree mit TObjectList
Aktuell fülle ich die Struktur mit:
Code:
Data := TDataClass.Create;
DataLst.Add(Data); Data.Zeitraum := '01/2019'; vnHead:= AddVSTStructureHeadClass(vstSP, nil, TDataClass(DataLst[0])); Data.Detail.Caption:='Zeile1:'; Data.Detail.Wert1 := 'Det1 - Wert1'; Data.Detail.Wert2 := 'Det1 - Wert2'; Data.Detail.Wert3 := 'Det1 - Wert3'; AddVSTStructureDetailClass(vstSP, vnHead, DataLst[0].Detail); Data.Detail.Caption:='Zeile2:'; Data.Detail.Wert1 := 'Det2 - Wert1'; Data.Detail.Wert2 := 'Det2 - Wert2'; Data.Detail.Wert3 := 'Det2 - Wert3'; AddVSTStructureDetailClass(vstSP, vnHead, DataLst[0].Detail); GetText:
Code:
procedure TForm5.vstSPGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; TextType: TVSTTextType; var CellText: string); var Data: PDataClass; Detail : PDetailClass; begin Detail := vstSP.GetNodeData(Node); if vstSP.GetNodeLevel(Node)=0 then begin Data := vstSP.GetNodeData(Node); Data := vstSP.GetNodeData(Node); case Column of 0: begin CellText := Data.Zeitraum; end; 1: CellText := ''; 2: CellText := ''; 3: CellText := ''; end; end; if vstSP.GetNodeLevel(Node)=1 then begin case Column of 0: CellText := Detail.Caption; 1: CellText := Detail.Wert1; 2: CellText := Detail.Wert2; 3: CellText := Detail.Wert3; end; end; end; Im Ergebnis wird für beide Childs nur Zeile 2 angezeigt :roll: |
AW: TVirtualStringTree mit TObjectList
Du musst für jeden Node eine eigene Instanz von TDataClass erzeugen und die auch in der DataLst speichern:
Delphi-Quellcode:
Data := TDataClass.Create;
DataLst.Add(Data); Data.Zeitraum := '01/2019'; vnHead:= AddVSTStructureHeadClass(vstSP, nil, Data); Data := TDataClass.Create; DataLst.Add(Data); Data.Detail.Caption:='Zeile1:'; Data.Detail.Wert1 := 'Det1 - Wert1'; Data.Detail.Wert2 := 'Det1 - Wert2'; Data.Detail.Wert3 := 'Det1 - Wert3'; AddVSTStructureDetailClass(vstSP, vnHead, Data.Detail); Data := TDataClass.Create; DataLst.Add(Data); Data.Detail.Caption:='Zeile2:'; Data.Detail.Wert1 := 'Det2 - Wert1'; Data.Detail.Wert2 := 'Det2 - Wert2'; Data.Detail.Wert3 := 'Det2 - Wert3'; AddVSTStructureDetailClass(vstSP, vnHead, Data.Detail); |
AW: TVirtualStringTree mit TObjectList
Argh :stupid:, dass war es!
Kann im Nachgang auch nicht anders funktionieren... Vielen Dank!!! |
AW: TVirtualStringTree mit TObjectList
Was mir noch aufgefallen ist: Das FreeNode des vst brauchst du nicht. Deine Data-Objekte werden ja von der DataLst verwaltet und freigegeben. Da ist es nicht gut, wenn der vst diese Objekte auf nil setzt.
|
AW: TVirtualStringTree mit TObjectList
Zitat:
Delphi-Quellcode:
setzen ist nicht schlimm. Er gibt es ja nicht frei. Schlimmer wäre es, wenn er es bereits freigeben würde. Dann gäbe es eine AV.
nil
Anders wäre das wenn er Interfaces nutzen würde. Dann muss er sie auch dort auf nil setzen, da sonst der Referenzzähler nicht dekrementiert wird. |
AW: TVirtualStringTree mit TObjectList
Zitat:
Außerdem könnte es ja sein, dass man die Items außerhalb des VST noch braucht. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:11 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz