![]() |
ListView Data befüllen?
Ich möchte gerne meinen Code etwas besser gestalten.
Ich habe eine ListView und aktuell füge ich einfach nur neue Einträge hinzu und greife auf die Caption zu. Ich möchte das gerne über eine Liste regeln denn das hätte auch den netten Effekt, dass ich an anderer Stelle im Programm auf das Laden aus einer ini-Datei verzichten könnte. Reicht hier eine TObjectList wo ich jedes erstellte Object einfach so dranhänge( teils Pseudo-Code):
Delphi-Quellcode:
Später greife ich dann auf MeineObjectList[irgendeinindex].irgendeinproperty zu. Ist das richtig so?
aItem := ListView1.Items.Add;
aItem.Caption := 'ABC'; aItem.SubItems.Add('123'); // Hier nun ein Item für die ObjectList erzeugen und ... aItem.Data := MeinObjectListItem; Acha das alles noch zusammen mit einem Record ist ja klar. Edit1 Hier mal wie ich es aktuell teste!
Delphi-Quellcode:
Edit2
type
PListViewData_Record = ^TListViewData_Record; TListViewData_Record = packed record Caption: string; end; // Button1 var aListViewObjectList_Record_Item: PListViewData_Record; begin New(aListViewObjectList_Record_Item); aListViewObjectList_Record_Item.Caption := 'Caption-' + IntToStr(Random(123)); ListView1.Selected.Data := aListViewObjectList_Record_Item; end; // Button2 ShowMessage(PListViewData_Record(ListView1.Selected.Data).Caption); // Button3 var i: Integer; begin for i := ListView1.Items.Count - 1 downto 0 do if ListView1.Items[i].Data <> nil then Dispose(PListViewData_Record(ListView1.Items[i].Data)); Hier meine neue Version. Vielleicht ist die besser?
Delphi-Quellcode:
type
PListViewData_Record = ^TListViewData_Record; TListViewData_Record = class Caption: string; end; var aListViewData_List: TList<TListViewData_Record>; // Liste erzeugen und Eintrag hinzufügen var aListViewObjectList_Record_Item: TListViewData_Record; begin // Liste erzeugen if aListViewData_List = nil then aListViewData_List := TList<TListViewData_Record>.Create; // Object erzeugen (Caption und alle SubItems) und an Data hängen aListViewObjectList_Record_Item := TListViewData_Record.Create; aListViewObjectList_Record_Item.Caption := ListView1.Selected.Caption; ListView1.Selected.Data := aListViewObjectList_Record_Item; // Objekt der Liste hinzufügen aListViewData_List.Add(aListViewObjectList_Record_Item); ShowMessage('Added: ' + aListViewObjectList_Record_Item.Caption + sLineBreak + 'Index in TList: ' + IntToStr(aListViewData_List.Count - 1)); end; // Data Caption anzeigen begin // Test: Data Caption anzeigen if ListView1.Selected.Data <> nil then ShowMessage(TListViewData_Record(ListView1.Selected.Data).Caption); // Alle Objekte und Liste löschen var i: Integer; begi for i := aListViewData_List.Count - 1 downto 0 do aListViewData_List.Items[i].Free; // Liste freigeben aListViewData_List.Free; aListViewData_List := nil; // Einen Eintrag in der Liste finden function getIndexInList(sCaption: string): SmallInt; var i: Integer; begin Result := -1; for i := 0 to aListViewData_List.Count - 1 do if AnsiSameText(aListViewData_List.Items[i].Caption, sCaption) then Result := i; end; var iIndex: Integer; begin iIndex := getIndexInList('123456'); if (iIndex > -1) and (iIndex <= aListViewData_List.Count - 1) then ShowMessage('Caption: ' + aListViewData_List.Items[iIndex].Caption + sLineBreak + 'Index in TList: ' + IntToStr(iIndex)); end; |
AW: ListView Data befüllen?
Wozu der Record? Objektinstanzen sind ja auch Pointer, die kann man da direkt hineingeben. Ich hab mal schnell ein Beispiel zusammengeklickert, es werden die Standard-Komponentennamen verwendet:
Delphi-Quellcode:
Jetzt sind die TDingens-Instanzen sowohl im Data-Feld des entsprechenden ListViewItems als auch in der Objektliste abgelegt. Das bedeutet dann aber, dass man nicht mehr auf Data zugreifen sollte, wenn die Liste bereits freigegeben wurde.
unit Unit5;
interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, System.Generics.Collections, Vcl.StdCtrls, Vcl.ComCtrls; type TDingens = class private FName: string; FZahl: integer; procedure SetName(const Value: string); procedure SetZahl(const Value: integer); public property Name: string read FName write SetName; property Zahl: integer read FZahl write SetZahl; end; TForm5 = class(TForm) ListView1: TListView; Button1: TButton; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); procedure FormDestroy(Sender: TObject); private { Private-Deklarationen } FListe: TObjectList<TDingens>; public { Public-Deklarationen } end; var Form5: TForm5; implementation {$R *.dfm} { TDingens } procedure TDingens.SetName(const Value: string); begin FName := Value; end; procedure TDingens.SetZahl(const Value: integer); begin FZahl := Value; end; procedure TForm5.Button1Click(Sender: TObject); var Dingens: TDingens; Item: TListItem; begin for Dingens in FListe do begin Item := ListView1.Items.Add; Item.Caption := Dingens.Name; Item.SubItems.Add(Dingens.Zahl.ToString); Item.Data := Dingens; end; end; procedure TForm5.FormCreate(Sender: TObject); var Dingens: TDingens; begin FListe := TObjectList<TDingens>.Create; Dingens := TDingens.Create; Dingens.Name := 'Hein Blöd'; Dingens.Zahl := 42; FListe.Add(Dingens); Dingens := TDingens.Create; Dingens.Name := 'Max Mustermann'; Dingens.Zahl := 100; FListe.Add(Dingens); Dingens := TDingens.Create; Dingens.Name := 'Klara Korn'; Dingens.Zahl := 3; FListe.Add(Dingens); Dingens := TDingens.Create; Dingens.Name := 'Rudi Rüssel'; Dingens.Zahl := 150; FListe.Add(Dingens); end; procedure TForm5.FormDestroy(Sender: TObject); begin FListe.Free; end; end. |
AW: ListView Data befüllen?
Mein Edit 2 im ersten Beitrag sollte doch in etwa dem entsprechen was du geschrieben hast richtig?
Trennung des Codes kommt bei mir erst später. Das hier ist ja nur ein Test. Sollte FListe.Free; bei dir nicht eigentlich MemoryLeaks für jedes TDingens hinterlassen? |
AW: ListView Data befüllen?
Ich weiß nicht, für mich sieht das recht umständlich aus. Ich würde erst einmal die Daten in der Objektliste ablegen und mich danach um die Darstellung kümmern. An das dem aktuellen ListViewItem zugeordneten Objekt kommst Du dann mit einem einfachen Typecast, wie Du es ja bereits tust.
Delphi-Quellcode:
Seit wann hinterlässt Free MemoryLeaks?
var
DeineKlasse: TDeineKlasse; begin DeineKlasse := TDeineKlasse(ListView.Selected.Data); if Assigned(DeineKlasse) then DeineKlasse.MachWas; |
AW: ListView Data befüllen?
Zitat:
Ich muss das aber leider so machen aufgrund des Aufbaus meiner Schleife. Ich gehe die Schleife lieber einmal durch statt zweimal. Vergess was ich da oben geschrieben habe. Zitat:
Zitat:
|
AW: ListView Data befüllen?
Wenn Du tatsächlich MemoryLeaks willst, nimm TList, ich nehme lieber TObjectList ;)
|
AW: ListView Data befüllen?
Ok diesen kleinen Unterschied kannte ich noch nicht. ich weiß zwar, dass TObjectList von TList kommt, aber dass letztes einen MemoryLeak erzeugt, wenn man die Einträge nicht explizit freigibt... wusste ich nicht.
Ich baue den Code heute Abend mal in mein Projekt ein und gucke was das wird. Ziel soll es u.a. sein, dass ich nicht mehr direkt auf ListView Caption, SubItem usw zugreifen muss sondern das dann alles über die Liste machbar ist. Dafür auch meine Funktion getIndexInList. |
AW: ListView Data befüllen?
Wenn Du über einen String in der Liste suchen willst, böte sich doch eine TStringList an. Da mit AddObject die Objekte rein, OwnsObjects auf true gesetzt, anschließend kannst Du mit IndexOf den passenden Eintrag ermitteln.
|
AW: ListView Data befüllen?
Das mit der StringList ist echt eine Idee.
Aber dann hätte ich vermutlich wieder wildes Gecaste wie...
Delphi-Quellcode:
// mit StringList:
TListViewData(aListViewData_List.Objects[i]).Caption // Mit TObjectList<TListViewData> aListViewData_List.Items[i].Caption |
AW: ListView Data befüllen?
Das verstehe ich jetzt nicht, aber ich kenne ja auch Dein Programm nicht.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:51 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