Delphi-PRAXiS
Seite 3 von 5     123 45      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Datenhaltung mit VirtualStringTree und Trennung der Businesslogik (https://www.delphipraxis.net/200152-datenhaltung-mit-virtualstringtree-und-trennung-der-businesslogik.html)

DieDolly 27. Mär 2019 16:57

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:

Leider habe ich immer noch Delphi 2007 im Einsatz darum gehen keine Generics.
Delphi Rio Community Edition womöglich eine Lösung?

jus 27. Mär 2019 22:19

AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
 
Zitat:

Zitat von DieDolly (Beitrag 1428910)
Zur Sicherheit würde ich immer einfügen ...
Delphi-Quellcode:
data:= Sender.GetNodeData(Node);

if not Assigned(data) //
 Exit; //
Zitat:

Leider habe ich immer noch Delphi 2007 im Einsatz darum gehen keine Generics.
Delphi Rio Community Edition womöglich eine Lösung?

yep... hast recht, sollte noch rein :thumb:

DieDolly 27. Mär 2019 22:24

AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
 
Und der Vollständigkeit halber, so gehts auch

Delphi-Quellcode:
data:= Sender.GetNodeData(Node);

if not data.IsAssigned then
 Exit;
Geschmackssache, was man wählt.

jus 27. Mär 2019 22:46

AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
 
Zitat:

Zitat von DieDolly (Beitrag 1428949)
Und der Vollständigkeit halber, so gehts auch

Delphi-Quellcode:
data:= Sender.GetNodeData(Node);

if not data.IsAssigned then
 Exit;
Geschmackssache, was man wählt.

Ich vermute, dass es bei den neueren VST den Befehl "data.IsAssigned" gibt. Bei meiner alten VST kennt er den Befehl noch nicht. Was bei meiner alten VST gerade noch aufgefallen ist, ist, dass mit der Prüfung von folgenden Befehl nicht getan ist, da es immer ASSIGNED ist:
Delphi-Quellcode:
data:= Sender.GetNodeData(Node);
if not Assigned(data) then Exit;
Es müßte eigentlich heissen, oder zumindest bei meiner alten VST Version unter Delphi 2007:
Delphi-Quellcode:
data:= Sender.GetNodeData(Node);
if not Assigned(data^.FObject) then Exit;
Lg,
jus

jus 27. Mär 2019 23:50

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:
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.
Dafür wurde das Verknüpfen in VSTBindObjectListUnit.pas ausgelagert.
Delphi-Quellcode:
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.
Wie schon vorher erwähnt für die Leute die noch ein Delphi 2007 im Einsatz haben.

Lg,
jus

DieDolly 28. Mär 2019 00:09

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.

generic 1. Apr 2019 12:36

AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
 
Code:
  PTreeData = ^TTreeData;
  TTreeData = record
    FObject : TObject;
  end;
Ich sehe immer diesen Quelltext.

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;

DieDolly 1. Apr 2019 13:46

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().

Codehunter 1. Apr 2019 16:58

AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
 
Zitat:

Zitat von generic (Beitrag 1429220)
Wieso speichert Ihr den Objekt Zeiger nicht direkt im VST?
Dann braucht ihr die Zwischenklasse TTreeData nicht.

Ich vermute, das sind Altlasten. Lange Zeit ging das beim VST gar nicht anders. Die alten Tutorials im Netz haben leider kein Verfallsdatum. Mir ging das ganz genauso: Ich nutze den VST schon seit den allerersten Tagen und hab eben die alten Vorgehensweisen verinnerlicht. Dass er inzwischen auch Generics kann, hab ich auch erst jetzt mitbekommen...

Zitat:

Zitat von DieDolly (Beitrag 1429225)
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().

Naja ganz so schlimm ist es nun auch wieder nicht. Kommt ganz auf den Einzelfall an. Wenn man eine Struktur von ein paar Dutzend Nodes hat (wie. z.B. in der Delphi-IDE die Projektverwaltung), dann ist es völlig Wumpe ob man iterativ mit AddChild arbeitet oder mit Root/Childcount. Im Zweifel opfere ich da sogar ein paar Millisekunden Runtime zugunsten lesbareren Codes.

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.

jus 1. Apr 2019 19:03

AW: Datenhaltung mit VirtualStringTree und Trennung der Businesslogik
 
Zitat:

Zitat von Codehunter (Beitrag 1429255)
Zitat:

Zitat von generic (Beitrag 1429220)
Wieso speichert Ihr den Objekt Zeiger nicht direkt im VST?
Dann braucht ihr die Zwischenklasse TTreeData nicht.

Ich vermute, das sind Altlasten. Lange Zeit ging das beim VST gar nicht anders. Die alten Tutorials im Netz haben leider kein Verfallsdatum. Mir ging das ganz genauso: Ich nutze den VST schon seit den allerersten Tagen und hab eben die alten Vorgehensweisen verinnerlicht. Dass er inzwischen auch Generics kann, hab ich auch erst jetzt mitbekommen...

Yep, ich habe mich bisher immer an das Tutorial gehalten. Vermutlich würde es auch direkt funktionieren. :oops:

Zitat:

Zitat von Codehunter (Beitrag 1429255)
Zitat:

Zitat von DieDolly (Beitrag 1429225)
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().

Naja ganz so schlimm ist es nun auch wieder nicht. Kommt ganz auf den Einzelfall an. Wenn man eine Struktur von ein paar Dutzend Nodes hat (wie. z.B. in der Delphi-IDE die Projektverwaltung), dann ist es völlig Wumpe ob man iterativ mit AddChild arbeitet oder mit Root/Childcount. Im Zweifel opfere ich da sogar ein paar Millisekunden Runtime zugunsten lesbareren Codes.

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.

Davon würde ich gerne mehr erfahren wollen? Also der Grund, warum man nicht AddChild verwenden soll, ist nur die Performance oder gibt es noch andere Gründe? Gab es Performancetests dazu?


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:28 Uhr.
Seite 3 von 5     123 45      

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