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/)
-   -   Delphi 2 Einträge in einem TListeView tauschen (https://www.delphipraxis.net/29886-2-eintraege-einem-tlisteview-tauschen.html)

jryan 16. Sep 2004 07:30


2 Einträge in einem TListeView tauschen
 
Hallo alle zusammen!

Ich stelle gerade meine Delphi-Kenntnisse mächtig in Frage und hoffe das mir irgendjemand helfen kann!
Folgendes Problem:
Ich benutze ein TListView um meine Daten darzustellen. Die Reihenfolge der Items ist dabei für mich von großer Bedeutung. Nun wollte ich eine Funktionalität implementieren, bei der das aktuell gewählte Item auf Buttonclick eine Position nach oben "wandert" (sprich mit dem darüberstehenden seinen Platz tauscht) und habe mir gedacht, das sollte wie folgt fuinktionieren:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  i:   Integer;
  temp: TListItem;
begin
  if (ListView1.SelCount > 0) then
  begin
    i := ListView1.Selected.Index;
    if (i > 0) then
    begin
      temp                := ListView1.Items[i-1]);
      ListView1.Items[i-1] := ListView1.Items[i];
      ListView1.Items[i]  := temp;
      ListView1.Selected  := ListView1.Items[i-1];
      ListView1.Invalidate;
    end;
  end;
end;
Leider führt dieser Quelltext nur dazu, dass mein gewähltes Elemnt immer nur das davor stehende Element überschreibt.

MfG
-jryan

Steve 16. Sep 2004 08:13

Re: 2 Einträge in einem TListeView tauschen
 
Hi,

schau Dir mal Delphi-Referenz durchsuchenAssign an :)

PS: temp erstmal erzeugen und dann wieder freigeben, nach dem Verschieben evtl. wieder Focus etc. korrekt setzen ;)

Gruß
Stephan

alcaeus 16. Sep 2004 08:31

Re: 2 Einträge in einem TListeView tauschen
 
Hi jryan,

du weißt der Variablen temp nicht das Element selbst zu, sondern nur den Pointer auf das Element. Nun überschreibst du das obere Element, und versuchst anschließend die Sicherungskopie zuzuweisen. Da diese aber weiterhin auf das (nun überschriebene) obere Element zeigt, wird der gleiche Wert nochmal zugewiesen.
Du musst deshalb ein Element löschen und anschließend mit Insert eine Stelle höher wieder einfügen.
Weiters: anstatt der zwei if-Abfragen kannst du auch eine verwenden:
Delphi-Quellcode:
i := ListView1.ItemIndex;
if (i > 0) then
...
Greetz
alcaeus

jryan 16. Sep 2004 10:57

Re: 2 Einträge in einem TListeView tauschen
 
Danke für die Hinweise!
Jetzt habe ich erstmal eine Version die funktioniert:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  i:   Integer;
  temp: TListItem;
begin
  i := ListView1.ItemIndex;
  if (i > 0) then
  begin
    try
      temp := TListItem.Create(ListView1.Items);
      temp.Assign(ListView1.Items[i-1]);
      ListView1.Items[i-1].Assign(ListView1.Items[i]);
      ListView1.Items[i].Assign(temp);
      ListView1.Selected  := ListView1.Items[i-1];
    finally
      temp.Free;
    end;
    ListView1.Invalidate;
  end;
end;
Wobei ich natürlich sagen muß, sehr ellegant ist das auf den ersten Blick nicht, da man ja die Daten zweimal im Rechner hin- und herschaufelt und dafür zusätzlichen Speicher braucht.
Gibt es eigentlich eine Alternative (Zeiger/Adressen) womit man das umgehen kann? (Ich hatte ja eigentlich bei meinen Ansatz gehofft, das er bei der ersten Zuweisung praktisch nur den Verweis auf das [i-1]. TListItem-Objekt in Temp speichert, bei der zweiten Zuweisung dann diesen Verweis aus [i-1] mit den Verweis auf [i] überschreibt und letzendlich dann den in temp gespeicherten Verweis auf das vormals [i-1] Objekt in [i] speichert. Habe dazu bei meiner Ausgangsversion auch schon mit ^ und @ rumgespielt, aber irgendwie ist es immer an Compilerfehlern gescheitert.)

MfG
-jryan

Phoenix 16. Sep 2004 11:50

Re: 2 Einträge in einem TListeView tauschen
 
Das kann so nicht klappen. Das Problem dabei ist, das der Index nicht vom Container sondern von den Elementen selber verwaltet wird. ISt ein wenig komplex, aber schau Dir vielleicht mal den Source von TList und TListItem an um Dir das zu gemüte zu führen.

Ich löse das so:
Delphi-Quellcode:
// exchange entries
//
procedure TForm1.exchangeEntries(const i, j: integer);
var
   l_Item: TListItem;
begin
   // do not exchange if a item does not exist
   if not checkItems(i,j) then // hier wird nur geprüft ob die items i und j der liste auch assigned sind...
      exit;

   lstListView.Items.BeginUpdate;

   l_Item := TListItem.Create(lstListView.Items);
   try
      // store item
      l_Item.Assign(lstListView.Items.Item[i]);

      // exchange items
      lstListView.Items.Item[i].Assign( lstListView.Items.Item[j] );
      lstListView.Items.Item[j].Assign( l_Item );
   finally
      l_item.Free;
      lstListView.Items.EndUpdate
   end;    
end;


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