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/)
-   -   TListView Column.Tag ändert sich mit D&D der Columns (https://www.delphipraxis.net/158177-tlistview-column-tag-aendert-sich-mit-d-d-der-columns.html)

ChrisE 8. Feb 2011 15:49

TListView Column.Tag ändert sich mit D&D der Columns
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,

Die Problembeschreibung:
Ein Formular mit einer Listview im ViewStyle vsReport. OwnerData ist true. Es werden verschieden Columns erzeugt. Diese erhalten um sie später indentifiezieren zu können in der Tag-Property eine Nummer. Im OnData-Event wird dann aufgrund der Tag-Eigenschaft entschieden welcher Wert ausgegeben werden soll.
(hier ein Beispiel für die Ausgabe:) )
Delphi-Quellcode:
procedure TForm52.ListView1Data(Sender: TObject; Item: TListItem);
var
  i: Integer;
  str_tmp: string;
begin
  with Item do
  begin
    for i := 0 to ListView1.Columns.Count - 1 do
    begin
      str_tmp := Format('Row:%d i:%d Tag:%d ID:%d Index:%d', [Item.Index, i, ListView1.Column[i].Tag, ListView1.Column[i].ID, ListView1.Column[i].Index]);
      if i = 0 then
      begin
        Item.Caption := str_tmp;
      end else
      begin
        Item.SubItems.Add(str_tmp);
      end;
    end;
  end;
end;
Der Anwender kann die Oberfläche umschalten zwischen "nur einen Eintrag auswählen" und eine Art Bearbeitungsmodus, in dem dann u.a. erlaubt sein soll viele Einträge zu selektieren.

Das Problem:
Wenn die Columns vom Anwender durch Drag&Drop verschoben werden, ändert sich u.a. die Tag-Eigenschaft der Columns ohne mein zutun. D.h. Die Column, wird im OnData-Event falsch wieder erkannt. Zu diesem Zeitpunkt scheint aber die Column-Nummer noch korrekt zu sein (also unverändert, obwohl jetzt an anderer Stelle).
Wird nun aber z.B. MultiSelect ein- oder ausgeschaltet stimmen die Werte für Tag wieder und die Column-Nummer entspricht auch wieder der "Sichtbarkeitsposition".
Grund dürfte das RecreateWND sein, dass hier intern aufgerufen wird, wenn der Wert von MultiSelect eines ListViews geändert wird.

Die Frage:
Wie relalisiere ich jetzt ein sauberes OnData-Event (Identifiezierung der Column)?
  • Die Tag-Eigenschaft ist nicht zuverlässig, da ich nicht weiß, ob der Anwender die Column verschoben hat oder nicht.
  • Die ID jeder Column ändert sich, sobald der Modus umgeschaltet wird (MultiSelect an/aus). Dann ist Tag aber wieder gültig.
  • Die Caption der Column kann nicht ausgewertet werden, da diese immer wieder andere Werte haben könnte
Außerdem bleibt die Frage offen, was passiert eigentlich, wenn ich z.B. einen Anwender habe der die Software immer offen läßt und den Modus ständig wechselt. ID ist ein Integer. Bei jedem Wechsel wird die ID um die Anzahl der Spalten in der Listview erhöht. Irgendwann läuft die ja auch über (auch wenn das vergleichsweise lange dauern dürfte)

Zur Vereinfachung habe ich ein kleines Beispiel angehängt.

Erstellt mit Delphi 2007 unter Win7.

Ich hoffe auf Antworten ;-)

Gruß, Chris

ChrisE 10. Feb 2011 06:26

AW: TListView Column.Tag ändert sich mit D&D der Columns
 
Hallo,

mal eine kurze Zwischenmeldung - ist kein Push ;-)

Es gibt einen erstmal vertretbaren Weg darüber, das RecreateWND immer nach einem Drag&Drop der Columns auf zu rufen.
Delphi-Quellcode:
procedure TForm52.ListView1ColumnDragged(Sender: TObject);
begin
  PostMessage(ListView1.Handle, CM_RECREATEWND, 0, 0);
end;
Das hat zumindest zur Folge, dass die Tags der Spalten tatsächlich immer stimmen. Das Problem bleibt aber weiter, dass die ID aller Spalten hierbei ansteigt. Das ist zwar genau so dokumentiert - also erstmal vollkommen i.O., aber dadurch dass es jetzt doch deutlich öfters vor kommt als sich die Herrn bei der Entwicklung dachten vielleicht jetzt doch ein Problem.

Daher nochmals meine Frage:
Ist das ein vertretbares Risiko (ID-Überlauf wegen Integer) oder sollte man hier dem Problem weiter nach gehen?

Gruß, Chris

ChrisE 16. Feb 2011 07:00

AW: TListView Column.Tag ändert sich mit D&D der Columns
 
*push*

Vielleicht gibt es ja doch jemanden, der hier was weiß

David Martens 17. Feb 2011 22:45

AW: TListView Column.Tag ändert sich mit D&D der Columns
 
Du kannst ja mal ein Bild anhängen um zu zeigen was du meinst.

Ich weiß nicht ob das hilft, aber probier doch mal die VirtualStringTree Komponente, ist war anfangs etwas kompliziert, aber wenn man sich etwas reinfuchst geht's schon.

Hier ein keines TUT.

ChrisE 18. Feb 2011 07:20

AW: TListView Column.Tag ändert sich mit D&D der Columns
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo David,

danke das du mir antwortest :-D

Zunächst zu VirtualStringTree: Diese Komponente kenne ich, wollte ihr Verwendung aber vermeiden. Außerdem weiß ich nicht wie es da mit der kommerziellen Nutzung aus sieht. Naja, und es läuft ja "eigentlich". Nur eben dieser Bug?!

Ich hatte in meinem ersten Beitrag ein Projekt angehängt, da es gar nicht so einfach ist zu beschreiben was ich meine. Im Endeffekt geht es darum, dass ich die Tag-Eigenschaft einer Column in einer Listview dafür verwende, dass ich identifizieren kann welche Daten hier rein sollen Delphi-Referenz durchsuchenTListView.OnData.

Das blöde ist nur, dass der Anwender zwei Dinge tun kann:
1. Er soll die Spalten dort hinschieben können wo er sie haben möchte
2. Er soll Multi-Select ein und ausschalten können

1. Funktioniert ja super, da muss man ja wenig machen. Nach dem Drag & Drop (D&D) hat auch jede Spalte ihren Namen. Nur die Tag-Eigenschaft stimmt nicht :-( Zwar stimmt noch die Stelle im Column-Array (i) aber das gilt auch nur solange kein "Recreate" läuft. Jetzt werden meine Daten falsch angezeigt, da die Identifizierung der Spalten in dem OnData-Event nicht mehr korrekt is :-(

Schaltet der Anwender jetzt aber Multi-Select ein/aus - läuft ein Recreate der Komonente. Jetzt stimmt die Tag-Eigenschaft auch wieder. Macht man das Recreate von Hand nach jedem D&D scheint erstmal alles ok. Nur die ID der Spalten wächst jedes mal um die Anzahl der Angezeigten Spalten. Also kommt es bei vielleicht irgendwann zu einem Overflow?

Ich versuche eine Foto-Streck an zu hängen.

Gruß, Chris

David Martens 18. Feb 2011 12:07

AW: TListView Column.Tag ändert sich mit D&D der Columns
 
Ein Vorschlag. Wenn deine Überschriften eindeutig sind, dann kannst du die Spalten darüber identifizieren. Das ganze ID und Tag Zeugs brauchst du dann nicht. Du kannst es auch ohne eindeutige Spaltennamen, indem du ein array of integer mit "IDs" füllst und die beim D&D aktualisierst.

Gruß David

ChrisE 18. Feb 2011 12:19

AW: TListView Column.Tag ändert sich mit D&D der Columns
 
Zitat:

Zitat von ChrisE (Beitrag 1080354)
  • Die Tag-Eigenschaft ist nicht zuverlässig, da ich nicht weiß, ob der Anwender die Column verschoben hat oder nicht.
  • Die ID jeder Column ändert sich, sobald der Modus umgeschaltet wird (MultiSelect an/aus). Dann ist Tag aber wieder gültig.
  • Die Caption der Column kann nicht ausgewertet werden, da diese immer wieder andere Werte haben könnte

OK, das mit den Column-Names müßte die einzige Lösung sein - dich ich aber so nicht wollte.

Aber das mit dem ID-Array funktioniert eben leider nicht. Denn wenn ich das ändere bei Drag&Drop weiß ich ja immer noch nicht welche Spalte ich ansprechen muss. Denn nach einem einfachen D&D bleibt der Index der Column (somit der zu Griff über Item.Caption oder Item.SubItems[i]) noch bestehen. Erst nach dem Recreate ändert sich alles. Und das bekomme ich ja ggf. nicht mal mit. Und dann stimmt auch mein eigenes Index-Array nicht.

Anbei, ich konnte das Problem ja soweit zähmen, dass ich weiter kommen konnte. (siehe Beitrag #2)

Aber das ist doch echt keine Lösung - das ist ein Workarround.

Und es bleibt die Frage, ob es ein VCL-Bug ist oder ob es mit anderen Dingen zusammen hängt die ich nur nicht verstehe :-)

Gruß, Chris


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