Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   VirtualTreeView mit DIContainers kombinieren (https://www.delphipraxis.net/204662-virtualtreeview-mit-dicontainers-kombinieren.html)

Wishmaster 17. Jun 2020 02:55

VirtualTreeView mit DIContainers kombinieren
 
Liste der Anhänge anzeigen (Anzahl: 1)
so ich versuche seit geraumer zeit die VirtualTreeView mit DIContainers zu kombinieren
ich habe zwei VirtualTreeView's die ich miteinander verlinken will. jede VirtualTreeView hat mehrere kolumnen
im endeffekt soll das genauso aussehen und funktionieren wie die "RegEdit" in windows.

ich will die die daten manuell eintragen, editieren, löschen und natürlich Speichern und Laden können.

ich habe eine funktionierende demeo gebastelt allerdings benutze ich da die Absolute Database


mit der Compo. DIContainers ich weiß nicht einmal wo ich anfangen soll. wäre jemand bereit mir ne kleine Demo zu schreiben?

siehe anhang wie das ganze aussehen soll

TiGü 17. Jun 2020 08:32

AW: VirtualTreeView mit DIContainers kombinieren
 
Ich kenne diese Komponentensammlung konkret nicht, aber beim lesen der Website erscheint es mir auch nur eine aufgebohrte Version von Listen- und anderen Datenklassen zu sein.
Im Prinzip verheiratest du den VirtualTreeView damit genauso bzw. so ähnlich, als wenn du eine normale Delphi TList/TList<T> o.ä. hättest.
Es finden sich im Forum zahlreiche Beispiele dafür, insbesondere die Beiträge von User Aviator sind immer sehr hilfreich.

Welche konkrete Datenklasse nutzt du denn aus den DIContainers (TDITree, TDIList, TDIHash...)?

Stevie 17. Jun 2020 08:58

AW: VirtualTreeView mit DIContainers kombinieren
 
Und für das Zeugs will der tatsächlich 118.99 Euro? :shock:
Benutz Spring4D - das ist Open Source ;) Eventuell noch den TreeviewPresenter aus DSharp und du hast das Ding schon fast fertig.

P.S. Echt unglücklich vom Author, das DIContainers zu nennen, als ich das Thema las, dachte ich wirklich an was anders

freimatz 17. Jun 2020 11:14

AW: VirtualTreeView mit DIContainers kombinieren
 
Ich auch. Habe kurz reinschaut. "Last modified: 2016". Ich sehe keine Vorteile das zu verwenden.

Wishmaster 19. Jun 2020 04:13

AW: VirtualTreeView mit DIContainers kombinieren
 
danke für die schnelle antwort.


@Stevie ich kannte die zwei komponenten nicht, ich habe sie installiert und nur kurz angeschaut, sehen vielversprechend aus.
ich muss nur rauskriegen wie ich nodes and subnodes kreieren kan. einige der demos funktionieren nicht mehr.


in der VirtualTreeviewSample demo habe ich den folgenden code gefunden, das erklärt aber nicht wie ich ne node und subnode (Node:= VSTree.AddChild) in der VirtualTreeview kreiere kan.
und natürlich wie ich das ganze Speicher/Lade
ich muss mich etwas mehr damit befassen. ich bin aber für jede hilfe/Demo dankbar.




Delphi-Quellcode:
procedure TMainForm.AddContactClick(Sender: TObject);
var
  LContact: TContact;
begin
  LContact := TContact.Create('FirstName', 'LastName');
  ContactsPresenter.View.ItemsSource.Add(LContact);
  ContactsPresenter.View.CurrentItem := LContact;
end;



procedure TMainForm.FormCreate(Sender: TObject);
var
  list: IList<TObject>;
begin
  list := TObservableCollection<TObject>.Create();
  list.Add(TContact.Create('John', 'Doe'));
  list.Add(TContact.Create('Jane', 'Doe'));
  list.Add(TContact.Create('Baby', 'Doe'));
  ContactsPresenter.View.ItemsSource := list as IObjectList;



 
  ....


ich habe versucht mit dem hersteller von der DIContainers Compo. zu arbeiten. aber bei der ersten frage wurde der so aggressive, da denkt man zweimal nach beforman im ne frage stellt.

Stevie 19. Jun 2020 09:03

AW: VirtualTreeView mit DIContainers kombinieren
 
Du erzeugst keine Nodes selber, du hängst eine IObjectList und ein oder mehrere DataTemplates an den TVP. Die DataTemplates bestimmen, welche Daten angezeigt werden und ob und welche Elemente in der Ebene darunter angezeigt werden.

jus 19. Jun 2020 09:05

AW: VirtualTreeView mit DIContainers kombinieren
 
ein Beipiel mit mehreren Ebenen gibt es hier. :)

jus

Aviator 19. Jun 2020 10:17

AW: VirtualTreeView mit DIContainers kombinieren
 
Liste der Anhänge anzeigen (Anzahl: 1)
Also im ersten Moment dachte ich bei DI auch an etwas anderes.

Ich habe jetzt einfach mal ein Beispiel gemacht, wie man einen VST auch mit einer
Delphi-Quellcode:
TObjectList<T>
befüllen kann. Vielleicht reicht dir das ja auch schon. Für totale VST Neulinge habe ich den Code auch etwas dokumentiert. Allerdings in Englisch, damit auch Nicht-Deutsche damit etwas anfangen können.

Vielleicht hilft es dir ja weiter.

Wishmaster 21. Jun 2020 21:25

AW: VirtualTreeView mit DIContainers kombinieren
 
noch einmal danke für die demo es ist aber leider nicht was ich wollte.
kann sein dass ich mich falsch ausgedrückt hatte aber mir ging es darum [2] VirtualTreeViews miteinander zu verbinden
ohne dabei auf eine DB zu setzen wie (Absolute Database), ich wollte meinen eigenen password manage schreibe wie das programm (KeePass)
woh jeder record/node eine dynamische größe hat und bem speichern nur die felder speichert die tatsächlich einen eintrag enthalten um so die Datei so klein wie möglich zu halten.
deswegen hatte ich ursprünglich die Compo DIContainers gewählt weil da ne demo drin ist "DIContainers_AddressBook" die sah vielversprechend aus.
doch leider kam ich da nicht weiter sie umzuschreiben damit ich [2] VirtualTreeViews benutzen kann mit unendlich vieleen einträge auf beider seiten.

ihr könnt euch das so vorstellen wie der file explore in windows. du klickst auf einen ordner auf der linken seite und auf der rechten seite werden die datein die in dem ordner drin sind angezeiget,
oder RegEdit


so wenn ihr euch das bild im ersten pos anschaut, weiß ich wie man die virtualTreeView mit Daten füllt, das ist nicht das problem.



@Aviator
die Demo ist überkompliziert und dasselbe kannst auch einfacher/schnell/kleiner machen mit nem normalen record. es sei denn ich übersehe etwas/ en forteil.



das ist die datenstrukture die ich vorher benutzt hatte mit der Absolute Database.

Delphi-Quellcode:
(**************************** Create Encrypted File ***************************)

function TMain_Form.Create_EncryptedFile(const Filename : String; DeletePass : Boolean) : Boolean;
//var GraphicCompressionAlgorithm: TCompressionAlgorithm;
begin
  Result:= False;
  DBFilename:= FileName;


 with SecureDB do
  begin
   if Exists then
    Close;
  end;

 with Folder_Table do
  begin
   if Exists then
    Close;
  end;

 with Record_Table do
  begin
   if Exists then
    Close;
  end;


 if not ShowPassDialog('Create a new Password database') then
  begin
   SecureDB.Password:= '';
   exit;
  end;


 if (Length(SecureDB.Password) = 0) then
  Exit;

 with SecureDB do
  begin
    DatabaseName:= 'SecureDB';
    DatabaseFileName:= DBFilename;
    PageSize:= 2048;
    PageCountInExtent:= 8;
    MaxConnections:= 1;
    MultiUser:= false;
    Exclusive:= true;
   if Exists then
    begin
     Close;
     DeleteDatabase;
    end;
  end;


 (* Folder Table *)

 with Folder_Table do
  begin
    DatabaseName:= 'SecureDB';
    TableName:= 'FolderList';
   with AdvFieldDefs do
    begin
     Clear;
     Add('ID', aftAutoIncLargeint, 0, false);
     Add('ParentID', aftLargeint);
     Add('IconId', aftLargeint);
     Add('Icon', aftGraphic, 0, false, caZLIB, 4);
     Add('Title', aftWidestring, 255);
    end;
   with IndexDefs do
    begin
     Clear;
     Add('ID', 'ID', [ixPrimary]);
     Add('ByParentID', 'ParentID', []);
     Add('ByTitle', 'Title', []);
    end
  end;

 (* Record Table *)

 with Record_Table do
  begin
    DatabaseName:= 'SecureDB';
    TableName:= 'RecordList';
   with AdvFieldDefs do
    begin
     Clear;
     Add('ID', aftAutoIncLargeint, 0, false);
     Add('ParentID', aftLargeint);
     Add('FolderID', aftLargeint);
     Add('Icon', aftGraphic, 0, false, caZLIB, 4);
     Add('Title', aftWidestring, 255);
     Add('Value', aftWideMemo, 0, False, caZLIB, 4);
     Add('Comment', aftWideMemo, 0, False, caZLIB, 4);
     Add('File', aftBlob, 0, False, caZLIB, 4);
     Add('FileName', aftWideMemo, 0, False, caZLIB, 4);
     Add('IsHidden', aftBoolean);
     Add('Colored', aftBoolean);
     Add('ItemColor', aftWidestring, 10);
     Add('FontColor', aftWidestring, 10);
     Add('FontBold', aftBoolean);
    end;
   with IndexDefs do
    begin
     Clear;
     Add('ID', 'ID', [ixPrimary]);
     Add('ByParentID', 'ParentID', [ixDescending]);  // RecordTree Folder
     Add('ByFolderID', 'FolderID', []);              // FolderTree Folder
     Add('ByTitle', 'Title', []);
    end;
  end;




  {
   FieldByName('ItemColor').AsWideString := ColorToHex(Data.ItemColor);
   FieldByName('FontColor').AsWideString := ColorToHex(Data.FontColor);
   FieldByName('FontBold').AsBoolean    := Data.FontBold;


  }


 try
 (* create the database *)
  with SecureDB do
   begin
    if not Exists then
     CreateDatabase;
   end;

  (* create the Folder Table table *)
  with Folder_Table do
   begin
    if not Exists then
     CreateTable;
   end;

  (* create the Record Table table *)
  with Record_Table do
   begin
    if not Exists then
     CreateTable;
   end;

  if DeletePass then
   SecureDB.Password:= '';
   Result:= True;

 except
  on E: Exception do

 end;
end;
Delphi-Quellcode:
(******************************* Fill Folder-List *****************************)

function TMain_Form.FolderList_Fill(ExpandedNood : Boolean) : boolean;
 procedure FillTreeNode(Parent: PVirtualNode);
 var Node: PVirtualNode;
     Data: PNodeData;

     // test
     BlobImage : TStream;
     Image : TBitmap;
 begin
  if Assigned(Parent) then
   begin

     Data:= FolderTree.GetNodeData(Parent);
     Folder_Table.Filter:= 'ParentID = ' + IntToStr(Data^.ID);
     Folder_Table.Filtered:= true;
     Folder_Table.First;

    while not Folder_Table.Eof do
     begin
      Node:= FolderTree.AddChild(Parent);
      Data:= FolderTree.GetNodeData(Node);
      Data^.ID:=    Folder_Table.FieldByName('ID').AsLargeInt;
      Data^.Title:= Folder_Table.FieldByName('Title').AsWideString;
      Data^.IconID:= Folder_Table.FieldByName('IconID').AsLargeInt;
      Folder_Table.Next;
     end;


     Node:= Parent.FirstChild;
    while Assigned(Node) do
     begin
      FillTreeNode(Node);
      FolderTree.Expanded[Node]:= true;
      Node:= Node.NextSibling;
     end;

   end;
 end;

 var Node, RootNode: PVirtualNode;
     Data: PNodeData;
begin
  Result:= False;
  FolderTree.BeginUpdate;
 try
  FolderTree.Clear;



  Node:= FolderTree.AddChild(Nil);
  Data:= FolderTree.GetNodeData(Node);
  Data^.ID:= 0;
  Data^.Title:= 'My Passwords';
  Data^.Value:= '';
  Data^.IconID:= 0;
  FillTreeNode(Node);

 (* Expand first nood 'My Passwords' *)
  RootNode:= FolderTree.GetFirst();
  FolderTree.Expanded[RootNode]:= ExpandedNood;
 finally
  FolderTree.EndUpdate;
  RecordTree_Fill(0, False);
  Result:= True;
 end;
end;
Delphi-Quellcode:
(******************************* Fill Record-List *****************************)


function TMain_Form.RecordTree_Fill(FolderID: Integer; ExpandedNood : Boolean): boolean;
var
 I : Integer;
 urlStartPos, urlStrLength: Integer;

procedure FillTreeNode(Parent : PVirtualNode);
var
 Node : PVirtualNode;
 Data : PNodeData;
 RecordData: TRecordData;
begin

 if Assigned(Parent) then
  begin
    Data:= RecordTree.GetNodeData(Parent);
    Record_Table.Filter:= 'ParentID = ' + IntToStr(Data^.ID)
    + ' ' + 'AND' + ' ' + 'FolderID = ' + IntToStr(FolderID);

    Record_Table.Filtered:= true;
    Record_Table.First;

   while not Record_Table.Eof do
    begin
     Node:=       RecordTree.AddChild(Parent);
     Data:=       RecordTree.GetNodeData(Node);

     Data^.ID:=   Record_Table.FieldByName('ID').AsLargeInt;
     Get_Record_Data(RecordData, true);
     Data^.Title:= RecordData.Title;
    if RecordData.IsHidden then
     Data^.Value:= '[xxxxxxxx]'
    else
     Data^.Value:= RecordData.Value;

    if not RecordData.IsHidden then
     Data^.IsLink:= IsURL(RecordData.Value)
    else
     Data^.IsLink:= False;

     Data^.ItemColored:= RecordData.ItemColored;
     Data^.ItemColor:=  RecordData.ItemColor;
     Data^.FontColor:=  RecordData.FontColor;
     Data^.FontBold:=   RecordData.FontBold;
     Data^.IconId:=     I;

     RecordListImg.Add(TImageHolder.Create);
     RecordListImg.Items[I].Image:= RecordData.Icon;

     Inc(I);
     Clear_Record_Data(RecordData);
     Record_Table.Next;
    end;

    Node:= Parent.FirstChild;
   while Assigned(Node) do
    begin
      FillTreeNode(Node);
      Node:= Node.NextSibling;
    end;

  end;
end;

var
 Node, RootNode: PVirtualNode;
 Data : PNodeData;
 Image : TBitmap;
 j : Integer;
begin
  Result:= False;
  RecordTree.BeginUpdate;

  RecordTree.Clear;

 for J:= RecordListImg.Count -1 downto 0 do
  RecordListImg.Delete(j);

 if RecordListImg.Count > 0 then
  RecordListImg.DeleteRange(0, RecordListImg.Count - 1);

 try
  Image := TBitmap.Create;
  Image.PixelFormat := pf32bit;
  Image.Width:= Record_ImList16.Width;
  Image.Height:= Record_ImList16.Height;
  Record_ImList16.GetBitmap(0, Image);

  RecordListImg.Add(TImageHolder.Create);
  RecordListImg.Items[0].Image:= Image;
  Image.Free;


  Node:= RecordTree.AddChild(Nil);
  Data:= RecordTree.GetNodeData(Node);
  Data^.ID:= 0;
  Data^.Title:= 'Root';
  Data^.IconId:= 0;
  I:= 1;

  FillTreeNode(Node);


 (* Expand first nood 'My Passwords' *)
  RootNode:= RecordTree.GetFirst();
  RecordTree.Expanded[RootNode]:= True;// ExpandedNood;
 finally
  RecordTree.EndUpdate;

  Result:= True;
 end;
end;

Aviator 22. Jun 2020 20:12

AW: VirtualTreeView mit DIContainers kombinieren
 
Zitat:

Zitat von Wishmaster (Beitrag 1467963)
ich wollte meinen eigenen password manage schreibe wie das programm (KeePass)
woh jeder record/node eine dynamische größe hat und bem speichern nur die felder speichert die tatsächlich einen eintrag enthalten um so die Datei so klein wie möglich zu halten.

Hier würde ich eher darauf setzen, einen entsprechend guten Serializer zu verwenden oder zu programmieren. JSON wäre hier sogar eine Option bei der alle Werte die
Delphi-Quellcode:
nil
sind nicht serialisiert werden. Somit hast du die geringst mögliche Textbasierte Form deiner Klasse. Du kannst dir natürlich auch einen eigenen Dateitypen generieren.
Aber all das hat nichts damit zu tun, wie du die Daten im Programm vorhälst. Und erst recht nicht damit, wie du die Daten nachher anzeigen möchtest.

Zitat:

Zitat von Wishmaster (Beitrag 1467963)
@Aviator
die Demo ist überkompliziert und dasselbe kannst auch einfacher/schnell/kleiner machen mit nem normalen record. es sei denn ich übersehe etwas/ en forteil.

Der Grund ist ganz einfach der, dass die Daten nicht vom VST sondern von einer, nicht von der Oberfläche abhängigen, ObjectList vorgehalten werden. An diese ObjectList kannst du alles anbinden was du willst. Prinzipiell das, was du auch mit dieser Komponentensammlung erreichen willst (so vermute ich).

Wenn du auf Records aufbaust, dann müsstest du das pro VST immer wieder machen. Und wenn du Records in einer Art Liste oder einem Array speichern willst, dann kannst du auch gleich eine Klasse verwenden und die Vorteile derer nutzen.

Mach es so wie du es für richtig hälst. Ich habe nur eine Demo mit, in meinen Augen, Best Practices vorbereitet. Zumindest hat es sich über viele Jahre dazu entwickelt und sich bisher immer wieder bewährt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:09 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