![]() |
Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Hallo,
ich versuche seit einiger Zeit ein paar von meinen Programmen zwischen GUI und Businesslogik aufzutrennen. Da kommt man dann vermutlich um die Begriffe wie MVVM oder generell MV* Sachen nicht mehr herum. Mich hat das MVVM Modell irgendwie eher zugesagt. Ich muß zu zugeben, dass ich noch nicht soweit bin, dass ich irgendwie konform mit dem MVVM Modell bin. Fürs Erste versuche ich mal das Programm auf 3 Schichten (GUI, Verbindungsschicht zwischen GUI und Businesslogik, Businesslogik) aufzutrennen. Im Prinzip speichere ich die benötigten Daten der GUI Komponenten(TEdit.Text, TCombox.Itemindex,...) in der Verbindungsschicht um diese bei Bedarf weiterverbeiten zu können. Da in in meinen Programmen aber öfters auch mal VirtualStringTree einsetze bin ich auf ein grundlegendes Dilemma für mich gestossen und hätte gerne Eure Expertenmeinung benötigt. Und zwar enthält der VST implizit die sämtliche Daten, die man dann mit "VSTIrgendwas.GetNodeData(Node)" aufruft. Bei mir ist es so, dass der VST-Node ein einfaches Datenrecord enthält. Doch irgendwie widerspricht es doch irgendwie meinem Verständnis, dass die GUI Komponente alle Daten beherbergt. Sollte es nicht eigentlich eher die darunterliegenden Schichten sein, die alle Daten enthalten und kennen? :gruebel: Derzeit mache ich es so, dass ich bei OnChange Ereignis von VST den Record von aktuell ausgewählten Node in die Verbindungsschicht mitschicke. Doch meine Frage ist, wir würde ihr das machen? Lg, jus |
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
MVVM ist ja mit Delphi wohl nicht so schön möglich wie bspw. mit C# und WPF. Zumindest gibt es hier im Forum diverse Threads darüber.
Bezüglich der Datenhaltung solltest du dir
Delphi-Quellcode:
anschauen. Dort werden deine Instanzen gespeichert. Die Node erhält dann als NodeData nur noch einen Pointer oder alternativ den ItemIndex das Objekt in der Liste. Zumindest mache ich das so und das hat sich auch bewährt. Die Daten können auch ohne Tree existieren und man kann problemlos mit ihnen arbeiten.
TObjectList<T>
|
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Hi,
vor einiger Zeit stand ich vor einem Ähnlichen Problem mit VST, weshalb ich mir eine Klasse geschrieben hat, die, die Daten in der gleichen Art und Weise handhabt, wie VST, diese aber eben nur verwaltet und nix mit der Darstellung zu tun hat. Ist vielleicht auch für dein Problem etwas ( ![]() |
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Zitat:
|
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Zitat:
|
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Ich bin mir nicht sicher aber ich finde die oben genannte Klasse macht alles nur noch viel komplizierter. Besonders für jemanden der noch nie was mit VST und paralleler Datenhaltung dafür zu tun hatte.
Mit einer ganz einfachen eventuell generischen TObjectList und 1 oder 2 Helferprozeduren, wenn überhaupt welche..., braucht man diese Klasse nicht. Selbstgeschriebener Code ist noch immer am besten. Den den versteht man auch am besten. Nur als kleines Beispiel, warum die Klasse eigentlich nicht notwendig ist.
Delphi-Quellcode:
Das da findet man schon von Haus aus im VST Code. Andere Sachen sicherlich auch.
function TVirtualNode.IsAssigned: Boolean;
// Returns False if this node is nil, True otherwise begin Exit(@Self <> nil); end; |
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Zitat:
![]() |
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Also eine sehr abgespeckte Variante wäre diese hier. (Aus dem Kopf geschrieben und auch nicht vollständig). Damit weist du der Node eine Objekt Instanz aus einer ObjectList zu. Dieses Objekt muss natürlich mit dem Index auch existieren. Beim Sortieren sollte sogar dann auch nichts passieren, da die Referenz ja bleibt. Es wird nur im Init Event einmal auf die ObjectList zugegriffen und das Item genommen, das mit dem NodeIndex übereinstimmt.
Delphi-Quellcode:
procedure TForm1.VSTInitNode(Sender: TBaseVirtualTree; Node: PVirtualNode; var InitialStates: TVTInitialStates);
var NodeData: PNodeData; begin NodeData := Sender.GetNodeData(Node); NodeData^ := ObjectList[Node^.Index]; end; |
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Wir nutzen dafür schon seit Jahren erfolgreich den TTreeViewPresenter aus DSharp. Der Übernimmt die Interaktion zwischen Daten (funktioniert über Spring4D IObjectList), Darstellungslogik (data template steuert, was wie ausgegeben und wie Daten strukturiert sind) und dem TVirtualTreeView.
|
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Ich würde es so machen
1. Datenklasse
Delphi-Quellcode:
2. Instanz(variable) der generischen Datenklassenliste bereitstellen und Datenklassenliste erzeugen
unit Datenklasse;
interface type TNodeData = class(TClass) private FText: string; public property Text: string read FText write SetText; end; type TNodeDataList = TObjectList<TNodeData>; implementation procedure TNodeData.SetText(const Value: string); begin FText:= 'Hallo ' + Value + '!'; end; end.
Delphi-Quellcode:
3. Daten der Liste hinzufügen
var // irgendwo ...
NodeDataList: TNodeDataList; // FormCreate oder so NodeDataList := NodeDataList.Create(True);
Delphi-Quellcode:
4. Node (löscht automatisch Datenklasseninstanz)
var
NodeData: TNodeData; begin NodeData := TNodeData.Create; NodeData.Text := 'jus'; NodeDataList.Add(NodeData); VST.RootCount := NodeDataList.Count;
Delphi-Quellcode:
5. Node im VST initialisieren
NodeDataList.Delete(2);
Delphi-Quellcode:
6. Node-Daten anzeigen
procedure TNodeEvents.VSTInitNode(Sender: TBaseVirtualTree; ParentNode, Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
begin Node.SetData<TNodeData>(NodeDataList[Node.Index]); end;
Delphi-Quellcode:
procedure TNodeEvents.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
var NodeData: TNodeData; begin NodeData := Node.GetData<TNodeData>; if not Assigned(NodeData) then Exit; case Column of 0: CellText := NodeData.Text; end; end; |
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
@DieDolly: Huch, seit wann kann denn der VST generische Daten? Ich nutz den schon soooo lange, dass ich immer noch mit klassischen Records arbeite. Geht auch, aber dein Beispiel würde hier auch vieles sehr vereinfachen. Irgendwie ist dieses Feature komplett an mir vorbei gegangen.
|
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Die OOP/generischen Ansätze gingen schon mehrmals hier durch die Praxis. Wie man sieht, jetzt schon wieder.
Ich benutze das VST nur noch so und es ist so unglaublich viel einfacher als vorher. Man braucht keine riesen Helferklassen im Hintergrund. Mein Beispiel ist das was man braucht, um seine Daten getrennt vom VST halten und managen zu können. Natürlich kommen noch mehr Properties und Helferprozeduren hinzu. Je nachdem was man denn braucht. Aber das ist dann noch immer einfacher als mit den hier erwähnten Helferklassen. |
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Zitat:
![]() Allerdings, wenn man mit dem VST noch nicht viel Erfahrung hat, kann einen das völlig erschlagen, dieses Featuremonster. Egal ob mit Records oder Generics. Man kann auch viele Vorteile zunichte machen, zum Bsp. wenn man iterativ Add() statt ChildCount verwendet. Wobei letzteres wiederum tricky ist bei der Initialisierung, wenn man keine indizierten Listen hat (z.B. TDictionary). |
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Ganz einfach erklärt kann man sich das so vorstellen.
Man stelle sich einen Node im VST vor. Jeder dieser Nodes hat nun als Datengrundlage eine komplette Instanz der TNodeData-Klassendaten. In der Natur vergleichbar mit einer Goldfruchtpalme. Jeder Strang ist ein Node und jeder Node hat eine Klasseninstanz mit allen Properties (die Blätter am Strang). Ich habe mich damit anfangs auch sehr schwer getan. Und eben deswegen habe ich dann auch erst Add() und sowas benutzt was das Ziel Daten von GUI trennen natürlich verfehlte. Irgendwann habe ich mich hingesetzt und einfach Code aus der Praxis abgeschrieben. Der Lerneffekt kommt dann irgendwann von alleine, wenn man mal selber eine listenbasierte Datenhaltung benötigt. |
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Wobei man der Versuchung widerstehen muss, seinen Datenobjekten in irgendeiner Form einen PVirtualNode als Property zu verpassen. Das geht schnell, dass man dann wieder versucht die Visualisierung aus den Datenobjekten heraus zu steuern.
Ich nutze den VST jedenfalls bevorzugt als Grid. Da gibt es IMHO nichts effizienteres. Schon gar nicht solche Schwergewichte wie z.B. DevExpress. Wenn man die Daten ohnehin schon irgendwo im Speicher rumliegen hat, braucht man die nicht noch drölfzig Mal hin und her alloziieren bis man sie mal auf den Bildschirm gepinselt hat. |
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Ich werfe mal einfach folgendes zur Diskussion bei:
Meine Geschäftslogik ruft Emails ab. D.h. ich habe eine Liste von Emails. Wenn ich diese Emails nun zur Anzeige bringen will, kommt die Darstellungsfrage auf. D.h. möchte ich diese z.B. nach Datum, Betreff oder Thread sortiert/gruppiert sehen. Abhängig davon würde ich jetzt anfangen meinen VST mit Knoten und Unterknoten zu erstellen. Die Knotendaten selbst sind aber nur ein Zeiger auf das Objekt in meiner Liste. Objekte verlinken hatte ich u.a. 2007 im Stammtisch #2 gezeigt: ![]() |
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Zitat:
![]() Ich selbst benutze die Generics auch kaum bis gar nicht. Ich arbeite nur noch mit Objekt Instanzen in einer TObjectList<T>. Und da noch ein
Delphi-Quellcode:
dazu zuschreiben stört mich weniger.
PClass = ^TClass
|
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Zitat:
|
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Zitat:
Delphi-Quellcode:
nicht benutze. Ich nutze eigentlich immer die standard Funktionen. Wahrscheinlich auch, weil ich eine Zeit lang kompatibel zu alten Versionen geblieben bin.
GetNodeData<T>
|
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Liste der Anhänge anzeigen (Anzahl: 1)
Vielen Dank an die Mitwirkenden, besonders Aviator und DieDolly. Leider habe ich immer noch Delphi 2007 im Einsatz darum gehen keine Generics.
Anbei der Ansatz für Leute, die noch ein altes Delphi wie ich einsetzen. Ich hoffe, dass ich da keinen logischen Fehler drin habe.
Delphi-Quellcode:
Lg,
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Contnrs, StdCtrls, VirtualTrees; type TNodeDataClass = class private FSpalte1: string; FSpalte2: string; FSpalte3: Integer; public property Spalte1: string read FSpalte1 write FSpalte1; property Spalte2: string read FSpalte2 write FSpalte2; property Spalte3: Integer read FSpalte3 write FSpalte3; end; PTreeData = ^TTreeData; TTreeData = record FObject : TObject; end; TForm1 = class(TForm) vst: TVirtualStringTree; Button1: TButton; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); procedure vstInitNode(Sender: TBaseVirtualTree; ParentNode, Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates); procedure vstGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString); private { Private-Deklarationen } DataList: TObjectList; public { Public-Deklarationen } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); var I: Integer; Node: PVirtualNode; begin VST.NodeDataSize := SizeOf(TTreeData); VST.RootNodeCount := DataList.Count; end; procedure TForm1.FormCreate(Sender: TObject); var i: Integer; NodeData: TNodeDataClass; begin DataList := TObjectList.Create; for i := 0 to 3 do begin NodeData := TNodeDataClass.Create; NodeData.Spalte1 := IntToStr(i); NodeData.Spalte2 := 'Spalte '+IntToStr(i); NodeData.Spalte3 := i; DataList.Add(NodeData); end; end; procedure TForm1.vstGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString); var data: PTreeData; begin data:= Sender.GetNodeData(Node); case Column of 0: CellText := TNodeDataClass(data^.FObject).FSpalte1; 1: CellText := TNodeDataClass(data^.FObject).FSpalte2; 2: CellText := IntToStr(TNodeDataClass(data^.FObject).FSpalte3); end; end; procedure TForm1.vstInitNode(Sender: TBaseVirtualTree; ParentNode, Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates); var data: PTreeData; begin data := Sender.GetNodeData(Node); data^.FObject := DataList[Node.Index]; end; end. jus |
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Zur Sicherheit würde ich immer einfügen ...
Delphi-Quellcode:
data:= Sender.GetNodeData(Node);
if not Assigned(data) // Exit; // Zitat:
|
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Zitat:
|
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Und der Vollständigkeit halber, so gehts auch
Delphi-Quellcode:
Geschmackssache, was man wählt.
data:= Sender.GetNodeData(Node);
if not data.IsAssigned then Exit; |
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Zitat:
Delphi-Quellcode:
Es müßte eigentlich heissen, oder zumindest bei meiner alten VST Version unter Delphi 2007:
data:= Sender.GetNodeData(Node);
if not Assigned(data) then Exit;
Delphi-Quellcode:
Lg,
data:= Sender.GetNodeData(Node);
if not Assigned(data^.FObject) then Exit; jus |
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Liste der Anhänge anzeigen (Anzahl: 1)
So zur späten Stunde noch eine neue Version mit einer kleinen Automatisierung beim Verknüpfen von VST mit TObjectList, indem ich eine neue Methode mit TBindVSTToObjectListHelperClass.BindVST einführe.
Die Code in TForm1.Button1Click ist ein bisschen kürzer geworden und TForm1.vstInitNode wurde entfernt.
Delphi-Quellcode:
Dafür wurde das Verknüpfen in VSTBindObjectListUnit.pas ausgelagert.
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Contnrs, StdCtrls, VirtualTrees, VSTBindObjectListUnit; type TNodeDataClass = class private FSpalte1: string; FSpalte2: string; FSpalte3: Integer; public property Spalte1: string read FSpalte1 write FSpalte1; property Spalte2: string read FSpalte2 write FSpalte2; property Spalte3: Integer read FSpalte3 write FSpalte3; end; TForm1 = class(TForm) vst: TVirtualStringTree; Button1: TButton; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); procedure vstGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString); private { Private-Deklarationen } DataList: TObjectList; public { Public-Deklarationen } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin TBindVSTToObjectListHelperClass.BindVST(VST,DataList); end; procedure TForm1.FormCreate(Sender: TObject); var i: Integer; NodeData: TNodeDataClass; begin DataList := TObjectList.Create; for i := 0 to 3 do begin NodeData := TNodeDataClass.Create; NodeData.Spalte1 := IntToStr(i); NodeData.Spalte2 := 'Spalte '+IntToStr(i); NodeData.Spalte3 := i; DataList.Add(NodeData); end; end; procedure TForm1.vstGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString); var data: PTreeData; begin data:= Sender.GetNodeData(Node); if not Assigned(data^.FObject) then Exit; case Column of 0: CellText := TNodeDataClass(data^.FObject).FSpalte1; 1: CellText := TNodeDataClass(data^.FObject).FSpalte2; 2: CellText := IntToStr(TNodeDataClass(data^.FObject).FSpalte3); end; end; end.
Delphi-Quellcode:
Wie schon vorher erwähnt für die Leute die noch ein Delphi 2007 im Einsatz haben.
unit VSTBindObjectListUnit;
interface uses Contnrs, VirtualTrees; type PTreeData = ^TTreeData; TTreeData = record FObject : TObject; end; TBindVSTToObjectListHelperClass = class private class var fObList: TObjectList; class var fVST: TVirtualStringTree; class procedure VstInitNode(Sender: TBaseVirtualTree; ParentNode, Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates); public class procedure BindVST(AVST: TVirtualStringTree; AObList: TObjectList); end; implementation { TBindVSTToObjectListHelperClass } class procedure TBindVSTToObjectListHelperClass.BindVST(AVST: TVirtualStringTree; AObList: TObjectList); begin if not assigned(AObList) then exit; fObList := AObList; fVST := AVST; fVST.Clear; fVST.NodeDataSize := SizeOf(TTreeData); fVST.OnInitNode := TBindVSTToObjectListHelperClass.VstInitNode; fVST.RootNodeCount := fObList.Count; end; class procedure TBindVSTToObjectListHelperClass.VstInitNode(Sender: TBaseVirtualTree; ParentNode, Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates); var data: PTreeData; begin data := fVST.GetNodeData(Node); data^.FObject := fObList[Node.Index]; end; end. Lg, jus |
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Denk dran RootNodeCount neu zu setzen, wenn du einen Eintrag aus deiner ObjectList löschst.
Ich glaube jedenfalls, dass das notwendig ist. |
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Code:
Ich sehe immer diesen Quelltext.
PTreeData = ^TTreeData;
TTreeData = record FObject : TObject; end; Wir sehen ein Zeiger auf ein Objekt welches in einen Record gespeichert wird. Also ist der Record genau so groß wie der Zeiger. Wieso speichert Ihr den Objekt Zeiger nicht direkt im VST? Dann braucht ihr die Zwischenklasse TTreeData nicht.
Code:
vst.NodeDataSize= sizeof(TMeinObjekt); // Zeigergröße - es geht auch TObject da alle Objektzeiger gleich groß sind.
vst.addChild(nil, MeinObjektInsatz); // Hinzufügen mit Zeigers var data: TMeinObjekt; begin data := TMeinObjekt(fVST.GetNodeData(Node)^); end; |
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
AddChild benutzt man nicht. Das ist eine Todsünde, so wie ich das immer lese.
Wenn man AddChild benutzt, dann kann man auch gleich ein TListView benutzen mit Add(). |
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Zitat:
Zitat:
Bei Anwendungen wie z.B. HeidiSQL, wo der VST hingegen ein Grid für viele Tausende Datensätze bilden kann, da macht das absolut Sinn. Wobei ich mich an der Stelle schon wieder Frage, ob die Vorteile die man mit Rootnodecount gewinnt, nicht durch das ganze Generics-RTTI-Gedönse wieder drauf geht. |
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Zitat:
Zitat:
|
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Zitat:
|
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Zitat:
Delphi-Quellcode:
bzw.
RootNodeCount
Delphi-Quellcode:
benutzt wird. Bei AddChild hingegen wird die Node direkt initialisiert. Zudem ist es mit
ChildCount
Delphi-Quellcode:
soweit ich weiß auch möglich, die NodeDaten erst dynamisch und zu dem Zeitpunkt zu laden an dem sie benötigt werden (eben virtuell).
RootNodeCount
Zum Schluss noch ein kleiner Auszug aus dem VirtualTreeView SourceCode zur
Delphi-Quellcode:
Methode.
AddChild()
Zitat:
|
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Zitat:
Ich will hier ja keinesfalls für die Verwendung von AddChild sprechen. Aber es gibt eben Anwendungsfälle, wo man mit dem Weg über ChildCount erhebliche Verrenkungen machen muss. Als grobe Orientierung kann man evtl. die Anzahl der zu erzeugenden Nodes nehmen. Oder auch die Frage, ob man mit Listen arbeitet oder nicht. Außerdem möchte ich noch darauf hinweisen, dass es die Methoden BeginUpdate und EndUpdate gibt. Dadurch kann man Initialisierungen direkt durch AddChild reduzieren. Außerdem lässt man den Rechenaufwand durch Initialisierung mit dem Gebrauch von ChildCount nicht einfach weg. Vielmehr geschieht er dann "wenn er gebraucht wird". Was in der Regel bedeutet, dass er bei der Visualisierung initialisiert wird. Das kann sogar von Nachteil sein, wenn die Initialisierung rechenintensiv ist und der Anwender viel vom Scrolling Gebrauch macht. |
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Zitat:
|
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Zitat:
Wenn mein VST 1.000.000 Nodes hat und aktuell wegen der kleinen Größe des Fensters nur 20 angezeigt werden, dann sollten doch eigentlich auch nur diese 20 initialisert werden. Oder nicht? Edit habe das gerade geprüft. Es werden alle auf einen schlag initialisiert. Egal ob aktuell sichtbar oder nicht. |
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Sorry, dass ich den Beitrag wieder aufwärme, aber bin auf ein weiteres Problem gestossen. Also der Ansatz mit der der TObjectList zur Verwaltung der Nodedaten in den vorigen Beträgen, wenn diese keine weiteren Unterebenen besitzen, funktioniert sehr gut. Doch wie sieht es dann aus, wenn die Nodes unterebenen besitzen? :gruebel:
lg, jus |
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Dann gibt es in deiner
Delphi-Quellcode:
eine zusätzliche Property die ebenfalls eine
TObjectList<T>
Delphi-Quellcode:
oder ein anderer ContainerType ist. Die ChildNodes verweisen dann auf einen Eintrag in dieser Liste. Wenn die Daten vom gleichen Typ sind (wie z.B. bei einer Verzeichnisstruktur), dann ist das recht einfach, da rekursiv. Bedenke, dass du dann im
TObjectList<T>
Delphi-Quellcode:
ein
Constructor
Delphi-Quellcode:
des ChildContainers und im
Create
Delphi-Quellcode:
ein
Destruktor
Delphi-Quellcode:
ausführen solltest.
Free
|
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Zitat:
Derzeit OHNE mehrere Unterebenen schaut es bei mir so aus:
Delphi-Quellcode:
Nach der Erweiterung von VST Nodes MIT mehreren Unterebenen:
unit Unit1;
interface //.... type TNodeDataClass = class private FSpalte1: string; FSpalte2: string; FSpalte3: Integer; public property Spalte1: string read FSpalte1 write FSpalte1; property Spalte2: string read FSpalte2 write FSpalte2; property Spalte3: Integer read FSpalte3 write FSpalte3; end; TForm1 = class(TForm) vst: TVirtualStringTree; procedure FormCreate(Sender: TObject); procedure vstInitNode(Sender: TBaseVirtualTree; ParentNode, Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates); procedure vstGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString); private DataList: TObjectList; //<--- hier die NodeObjekte von TNodeDataClass end; var Form1: TForm1; implementation
Delphi-Quellcode:
unit Unit1;
interface //.... type TNodeDataClass = class private FParentNode: TNodeDataClass; // <------ eine Referenz auf oberen Knoten notwendig???????? FSpalte1: string; FSpalte2: string; FSpalte3: Integer; FSubNodeDataList: TObjectList; // <- Für eventuelle Subnodes public property Spalte1: string read FSpalte1 write FSpalte1; property Spalte2: string read FSpalte2 write FSpalte2; property Spalte3: Integer read FSpalte3 write FSpalte3; end; TForm1 = class(TForm) vst: TVirtualStringTree; procedure FormCreate(Sender: TObject); procedure vstInitNode(Sender: TBaseVirtualTree; ParentNode, Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates); procedure vstGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString); private RootNodeDataList: TObjectList; //<--- hier die NodeObjekte von TNodeDataClass end; var Form1: TForm1; implementation |
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Naja du könntest so etwas machen:
Delphi-Quellcode:
type
TNodeDataClass = class private FParentNodeData: TNodeDataClass; FSpalte1: string; FSpalte2: string; FSpalte3: Integer; public constructor Create(AParent: TNodeDataClass); override; property Spalte1: string read FSpalte1 write FSpalte1; property Spalte2: string read FSpalte2 write FSpalte2; property Spalte3: Integer read FSpalte3 write FSpalte3; end; implementation constructor TNodeDataClass.Create(AParent: TNodeDataClass); begin inherited Create; FParentNodeData := AParent; end; |
AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
Zitat:
Wenn die Knotenanzahl fest steht, dann der VST direkt den gesamten benötigten Speichern mit einer Anfrage belegen. Durch die Ereignisse können dieser dann "on demand" befüllt werden. Also von der Geschwindigkeit her - hervorragend. Ich persönlich habe das aber nie genutzt, weil es die Software imho schwieriger macht. Man muss ggf. seine DB-Komponente globaler haben und die so lange offen lassen bis alles geladen ist. Callbacks sind eh nicht jedermanns Stärke. Zitat:
AddChild hat nur den Nachteil, dass jeweils nur für ein Element der Speicher geholt wird. Hast du mal ein Link für mich, wo ICH mich schlauer machen kann? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:54 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 by Thomas Breitkreuz