Verwendung von TListItem.Data

Rund um die LCL und andere Komponenten
Antworten
Kay
Beiträge: 134
Registriert: So 14. Nov 2010, 15:17

Verwendung von TListItem.Data

Beitrag von Kay »

Hallo,

ich hätte zwei Fragen zur Verwendung der Data-Eigenschaft von TListItem.

Ich möchte eine Listenansicht bauen, in der ich Beschreibungen zu laufenden Projekten anzeige. Jede Projektbeschreibung besteht beispielsweise aus einem Titel und einem Typ.
Zusätzlich möchte ich zu jedem Projekt erfassen, in welchem Ordner sich die zugehörigen Programmdateien befinden und aus wie vielen Dateien das Projekt besteht. Diese Informationen sollen allerdings nicht angezeigt, sondern lediglich in die Listenansicht "eingelagert" werden.

Das Ganze könnte also wie folgt ausschauen:

Code: Alles auswählen

type
  TDetails = class
  private
    FFileCount: Integer;
    FLocation: String;
  public
    constructor Create(AFileCount: Integer; ALocation: String);
    property FileCount: Integer read FFileCount;
    property Location: String read FLocation;
  end;
 
constructor TDetails.Create(AFileCount: Integer; ALocation: String);
begin
  FFileCount := AFileCount;
  FLocation := ALocation;
end;
 
procedure TForm1.FormCreate(Sender: TObject);
var
  ListItem: TListItem;
begin
  ListItem := ListView1.Items.Add;
  ListItem.Caption := 'Erstes Projekt';
  ListItem.SubItems.Add('Webanwendung');
  ListItem.Data := TDetails.Create(12, 'C:\MyWebApp');
 
  ListItem := ListView1.Items.Add;
  ListItem.Caption := 'Zweites Projekt';
  ListItem.SubItems.Add('Grafikprogramm');
  ListItem.Data := TDetails.Create(20, 'C:\MyGraphTool');
end;
Nun ist es ja so, dass sowohl die ListView als auch die hinzugefügten Listenelemente bei der Zerstörung des Formulars automatisch mit freigegeben werden. Aber gilt das auch für die in Data abgelegten Objekte oder müsste ich diese "manuell" freigeben, also beispielsweise mittels der folgenden Schleife:

Code: Alles auswählen

for I := 0 to ListView1.Items.Count - 1 do TDetails(ListView1.Items[I].Data).Free;
Und bei welchem Formularereignis müsste ich die Codezeile platzieren, bei OnClose oder OnDestroy?

Meine zweite Frage bezieht sich auf den Austausch von Listenelementen, d.h. es gibt Funktionen in meinem Programm, in denen ich den Inhalt von TListItem 1 auf TListItem 2 übertagen möchte und umgekehrt.

Das sieht bisher so aus:

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
begin
  SwapItems(ListView1.Items[0], ListView1.Items[1]);
end;
 
procedure TForm1.SwapItems(Item1, Item2: TListItem);
var
  S: String;
  SL: TStringList;
begin
  S := Item1.Caption;
  Item1.Caption := Item2.Caption;
  Item2.Caption := S;
 
  SL := TStringList.Create;
  SL.Assign(Item1.SubItems);
  Item1.SubItems.Assign(Item2.SubItems);
  Item2.SubItems.Assign(SL);
  SL.Free;
end;
Aber wie lassen sich jetzt meine Details-Objekte in der Data-Eigenschaft wechseln, ohne dass ich anschließend Zeigerkonflikte riskiere?
Gibt es eventuell auch noch eine simplere Möglichkeit, Listeneinträge zu tauschen, möglicherweise gleich direkt in der TListItems-Collection oder muss ich das zwingend so machen wie oben angegeben?

Vielen Dank und viele Grüße
Zuletzt geändert von Lori am Fr 28. Jun 2013, 16:28, insgesamt 1-mal geändert.
Grund: Bitte auch mal den richtigen Highlighter verwenden. Danke.

Benutzeravatar
theo
Beiträge: 10907
Registriert: Mo 11. Sep 2006, 19:01

Re: Verwendung von TListItem.Data

Beitrag von theo »

A: Ja, ein unbestimmter Pointer wird nicht automatisch freigegeben. Bei OnClose ist sicher nicht falsch.
B: ListView1.Items.Exchange(A,B); könnte helfen.

Antworten