Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Treeview: Parent löscht die Daten meiner CustomNode (https://www.delphipraxis.net/200979-treeview-parent-loescht-die-daten-meiner-customnode.html)

geesmith 13. Jun 2019 09:27

Treeview: Parent löscht die Daten meiner CustomNode
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich benutze eine TreeView und möchte in den einzelnen Nodes zusätzliche Daten speichern.

Um zusätzliche Daten in einer Treeview-Node zu halten, hatte ich mich daher nach Möglichkeiten für eine eigene TTreeNode-Klasse kundig gemacht.
Diese Möglichkeit hatte ich dann gefunden:
https://www.thoughtco.com/store-more...e-view-1058354

Das funktioniert soweit wunderbar... bis ich Frames verwende.

Für meinen Testaufbau und um euch das Problem zu zeigen habe ich folgendes:

unit unit1:
Delphi-Quellcode:
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, u_Frame;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  With TFrame2.Create(self) do
  begin
    ShowData;
    Parent := Self;
    ShowData;
  end;
end;

end.
unit u_Frame:
Delphi-Quellcode:
unit u_Frame;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ComCtrls;

type TCustomNode = class(TTreeNode)
  public
    MyData:String;
end;


type
  TFrame2 = class(TFrame)
    TreeView1: TTreeView;
    procedure TreeView1CreateNodeClass(Sender: TCustomTreeView;
      var NodeClass: TTreeNodeClass);
  private
    { Private-Deklarationen }
  public
    constructor Create(AOwner:Tcomponent); Override;
    procedure ShowData;
  end;

implementation

{$R *.dfm}

{ TFrame2 }

constructor TFrame2.Create(AOwner: Tcomponent);
begin
  inherited Create(AOwner);

  TreeView1.Items.Clear;
  With (TreeView1.Items.AddFirst(nil,'Meine Node') as TCustomNode) do
    MyData := 'abcdef';
end;

procedure TFrame2.ShowData;
begin
  ShowMessage('Meine Daten: '+(TreeView1.Items[0] as TCustomNode).MyData);
end;

procedure TFrame2.TreeView1CreateNodeClass(Sender: TCustomTreeView;
  var NodeClass: TTreeNodeClass);
begin
  NodeClass := TCustomNode;
end;

end.

Der Ablauf ist einfach gehalten:
- Im FormCreate erstellt er das Frame mit meiner TreeView drauf.
- Beim Erstellen des Frames wird eine Node meiner Klasse TCustomNode erstellt. Eine Variable wird mit dem Beispielwert 'abcdef' gefüllt
- Sobald das Frame auf der Form erstellt wurde, zeige ich mit ShowData die Daten der Node an. Das mache ich zweimal: Einmal vor 'Parent := ' und einmal nach.

Ergebnis:
- Beim ersten Mal anzeigen wird 'abcdef' angezeigt ... und beim zweiten Mal '' nichts.

Folgerung:
- Die Zuweisung 'Parent := ' sorgt dafür, dass mein Variablen in meiner Custom-Node geleert werden.


Fragen an euch:
- Wisst ihr warum?
- Mache ich was falsch?
- Gibt es bessere Möglichkeiten?


Grundsätzlich könnte ich damit umgehen, indem ich meine Custom-Node-Werte erst nach dem 'Parent := ' lade. Aber das ganze löst bei mir ein flaues Magengefühl aus und wenn ich noch Frames in Frames verwendet, dann wirds langsam aber sicher kompliziert dieses Verhalten zu berücksichtigen. Am Schluss bin ich übermässig mit Fehlersuche beschäftigt.

Vielen Dank für eure Hilfe!


Ich verwende Delphi 10.1.

peterbelow 13. Jun 2019 16:44

AW: Treeview: Parent löscht die Daten meiner CustomNode
 
Zitat:

Zitat von geesmith (Beitrag 1434530)
Ich benutze eine TreeView und möchte in den einzelnen Nodes zusätzliche Daten speichern.

Delphi-Quellcode:
type TCustomNode = class(TTreeNode)
  public
    MyData:String;
end;
Folgerung:
- Die Zuweisung 'Parent := ' sorgt dafür, dass mein Variablen in meiner Custom-Node geleert werden.

Fragen an euch:
- Wisst ihr warum?
- Mache ich was falsch?
- Gibt es bessere Möglichkeiten?

TTreeeview ist ein Windows custom control und die Nodes werden intern von Windows verwaltet, wobei die VCL aber halt einen "Überbau" in Form von TTreeNode et Cie. bereitstellt, um den ganzen hässlichen API-Kram zu verbergen. Aber so ganz geht das nicht. Wenn das Window handle eines TTreeview zum ersten mal angelegt wird werden die API-Level nodes erzeugt und mit den eventuell zur Design-Zeit angelegten TTReenode-Daten initialisiert. Wenn sich das Handle dann später ändert, z. B. weil das eines Forms oder Panels oder wo immer der Treeview enthalten ist neu angelegt wird, wird das Control auf dem API-level komplett neu erzeugt und dabei werden alle existierenden API-level Nodes zerstört. Damit die Daten des Treeviews das überleben speichert die VCl die komplette TTreenode-Collection in einem TMemoryStream (in DestroyWnd des TTreeview) und rekonstruiert die dann, wenn das neue Windowhandle angelegt wurde, aus diesem Stream.

Leider weis die VCL nichts von deinen zusätzlichen Daten in TCustomNode, deshalb überleben die die Änderung des Handles nicht. Früher konnte man das selbst nachflicken, da die entsprechenden Methoden (ReadNodeData und WriteNodeData) in TTreenode protected und virtual waren. Leider sind sie das nicht mehr in neueren Versionen der VCL (hat wohl was mit der Unterstützung von 64 bit Anwendungen zu tun), wie ich gerade feststellen mußte. Dadurch ist es leider reichlich unnütz geworden, eine eigene Nodeklasse zu verwenden. Da hat jemand definitiv was kaputt gemacht...

Wenn Du also mehr Daten an einen Node binden willst geht das nur noch über die Data-Property.

hoika 13. Jun 2019 17:19

AW: Treeview: Parent löscht die Daten meiner CustomNode
 
Hallo,
hm, warum verwendest du nicht das Feld
Zitat:

Data
, was doch genau dafür genutzt werden gedacht ist.
Also keine Ableitung machen.

http://docs.embarcadero.com/products...Node_Data.html
OK; du musst eine Klasse erzeugen, aber na und?

type
TNodeData = class
MyString: String;
end;

geesmith 14. Jun 2019 07:32

AW: Treeview: Parent löscht die Daten meiner CustomNode
 
Herzlichen Dank Ihr zwei und danke für die Erklärung. Unter diesem Aspekt ist das Verhalten nachvollziehbar. Allerdings doch sehr bedauerlich.

Ja, die Daten in der Data-Property zu verstauen wäre die Alternative. Das hatte ich vor meiner CustomNode auch so gehabt. Da ich in der TreeView jedoch diverse Anpassungen mache (Neue Node, Node löschen, Node editieren...), musste ich immer auch schauen, dass das Data-Objekt sauber gehandelt wird und da erschien mir die Möglichkeit einer CustomNode sehr attraktiv, da sehr einfach.

hoika 14. Jun 2019 08:11

AW: Treeview: Parent löscht die Daten meiner CustomNode
 
Hallo,
das Data-Property bleibt doch eigentlich auch erhalten,
also benutze deine abgeleitete Klasse, aber pack deine eigenen Sachen als Objekt ins Data rein.

Du könntest sogar deine eigenen Properties behalten und holst dir im
jeweiligen Get und Set das aus dem Data-Objekt.

geesmith 14. Jun 2019 08:39

AW: Treeview: Parent löscht die Daten meiner CustomNode
 
Danke hoika

So werde ich das machen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:59 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz