Die Advanced Polylist Komponenten (einzeln erhältlich oder innerhalb des TMS Components Pack oder größerer Pakete) bieten eine extrem flexible und moderne Art um praktisch jede Art einer Listensammlung der unterschiedlichsten Elemente (Items) zu erstellen. Die Items können aus Bild+Text, nur Text, HTML, Sektionsüberschriften und vielen mehr bestehen und auch kombiniert werden. Es können sogar eigene Elemente abgeleitet werden werden. Die TMS Advanced Poly List – Listen selber können z.B. horizontal oder vertikal sein. Dieser Artikel beschreibt nun wie Sie diese Polylisten dynamisch erzeugen können.
In meiner Aufgabenverwaltungs Software kommen diese Komponenten z.B. im Systemmenü oder auch im Register ‚Mein Tag‘ zum Einsatz. Das Register ‚Mein Tag‘ listet alle anstehenden Aufgaben und Termine des aktuellen Tages (oder eines anderen Tages, wenn ausgewählt).
Das Erstellen der Liste muss dabei natürlich dynamisch geschehen, da ja nicht vorher bekannt ist, welche Aufgaben oder Termine anfallen. So, wie geht man dabei vor?
Für die Liste selber zieht man aus dem Delphi-Toolbox-Panel TMS-Poly einfach eine Vertikale Liste auf das Formular (genauer gesagt eine TAdvVerticalPolyList). Im Programm wird diese als dayliste benannt.
Da die Liste dynamisch generiert werden soll, muss nicht all zu viel an den Einstellungen vorgenommen werden. Was aber bereits im Designmodus geschehen kann ist das Hinzufügen einer Überschrift. Hierzu doppelklickt man die Liste, es öffnet sich der Design Editor (Container Items Editor).Links hat man verschiedene Arten von Elementen, wie z.B. Button Bar Item, Header Item, Text Item und viele andere.
Für die Überschrift habe ich ein Element vom Typ THeaderItem gewählt. Wie der Name schon sagt, ideal um eine Hauptüberschrift für die Liste festzulegen. Im Objektinspektor von Delphi können Sie nun Titel, Farbe und viele andere Eigenschaften entsprechend Ihres persönlichen Wunsches definieren. Dies aber nur um ein Gefühl zu entwickeln wie das Ganze später aussehen soll, tatsächlich werden wir alle Elemente dynamisch anlegen.
Es empfiehlt sich auch ein Standardelement auf die Liste zu ziehen (in meinen Fall ein TImageTextItem).
Warum nun das Ganze? wir wollen die Liste doch dynamisch generieren…
1. weil man nach Anklicken immer schnell die möglichen Eigenschaften/Events sich anzeigen lassen kann, die wichtig bei Codebasierten Erstellen sind, spart einfach Zeit
2. weil man bereits die notwendigen Events für den Codebereich definieren kann, wie OnItemDblClick, dies erspart einfach das manuelle Erfassen.
3. weil man ein Gefühl für das Aussehen schon vorab bekommt
Das reicht dann aber schon im Designmodus, nun gilt es im Codeeditor des Formulars (oder als Klasse in einer separaten Unit) den Code zu schreiben, um die Liste dynamisch zu erstellen:
Der Code ist natürlich nur ein Beispiel basierend auf mein EasyTodo, für Ihre Zwecke werden Sie das Ganze natürlich anpassen.
Legen Sie nun eine Prozedur an:
procedure TfrmMeinTag.GetMeinTag(xdate: TDatetime); // xdate wäre dann immer der gewünschte Tag, z.B. einfach Date()) var // das Listenelement, welches für die Überschrift Anwendung findet nHeaderitem: THeaderItem; // für die einzelnen Listenelemente, die die // Datenbankeinträge repräsentieren werden aItem: TImageTextItem;
Sie beginnen dies mit
begin dayliste.BeginUpdate; // um das Zeichnen zu verbergen dayListe.ClearItems;
Um nun die Überschrift anzulegen:
nSitem := TSectionItem(dayliste.AddItem(TSectionItem)); nsitem.Caption := 'Aktueller Tag: ' + Wochentag(xDate) + ', ' + DateToStr(xdate); nsItem.Height := 50; nsItem.name := 'U1';
In unserem EasyTodo Beispiel haben wir 2 Listen, Aufgaben und Termine
– beide sollen durch eine Sektionsüberschrift voneinander abgesetzt werden
nHeaderitem := THeaderItem(dayliste.AddItem(THeaderItem)); // die Sektionsüberschrift für Aufgaben, erstellt //mit einem Headeritem NHeaderItem.Caption := 'Heutige Aufgaben'; // wichtig, sonst wird ein Dummyhintergrund gezeichnet nHeaderItem.Image := nil; // ein Bild aus einer Imagelist, die der Polyliste zugewiesen ist nHeaderItem.ImageIndex := 9; nHeaderItem.ImageHeight := 16; nHeaderItem.Imagewidth := 16; nHeaderItem.Name := 'Header1'; nHeaderItem.Spacing := 5;
Dies können Sie natürlich verändern oder erweitern, mögliche Einstellungen erhalten Sie, wenn Sie in den Formularmodus wechseln und den Designeditor der Polyliste aufrufen, unser Beispielelelement für die Überschrift auswählen und im Objektinspektor ein wenig mit den Einstellungen experimentieren.
Gut, nun gilt es die Sektion mit Leben zu erfüllen, hierzu erstellen wir für jede Aufgabe aus der Datenbank, die zum angegebenen Datum xDate passt ein Element vom Typ
TImageTextItem, Sie können natürlich auch ein anderes Element wählen, aber ist ja mein Beispiel :)
Das Ganze wird aus einer Datenbank, genauer gesagt eine (SQL-)Query gespeist:
while not myquery.eof do begin // legt ein neues Element vom Typ TImageTextItem an aItem := TImageTextItem(dayliste.AddItem(TImageTextItem)); // als Überschrift der Text, der die Aufgabe beschreibt aItem.Caption := nyQuery.FieldByName('aufgabe').AsString;
Um die Elemente später auswerten zu können, z.B. bei einem Clickevent, müssen wir diese natürlich identifizieren können, daher ist eine eindeutige Namensgebung zwingend notwendig, wir bilden diese Namen aus der Kombination „A_“ und einem Feldwert, in diesem Fall ein eindeutiges (AutoIncrement) Feld mit Namen ID, dieses enthält also eine Nummer, die nur einmal in der Datenbank vorkommt. Über das „A_“ können wir eindeutig abfragen, dass das Element eine Aufgabe beschreibt.
aItem.Name := 'A_' + myQuery.Fielddbyname('ID').AsString; aItem.height := 45; // beschreibt die Aufgabe mit Datum/Zeit und geschätztem Zeitaufwand // in Description aItem.Description := 'Um ' + myQuery.FieldByName('Datum').asString + ' Dauer: ' +myQuery.FieldByName('Zeitaufwand').AsString; // wichtig, sonst wird ein Dummyhintergrund gezeichnet aItem.Image := nil; // wird ausgeführt wenn das Element einmal angeklickt wird aItem.OnItemClick := ImageTextItem1ItemClick; // oder bei Doppelklick aItem.OnItemDblClick := ImageTextItem1ItemDblClick; aItem.CaptionColor := clblack;
Sie können dem Element eine Farbe zuweisen, die dieses kennzeichnet in Abhängigkeit von einem bestimmten Datenbankwert, so dass ein Anwender z.B. schnell erkennen kann, ob eine Aufgabe erledigt ist. In Easytodo selbst ist dies dann noch etwas mehr verfeinert
if myQuery.FieldByName('Status').AsInteger = 2 then aItem.CaptionColor := clgray else aItem.CaptionColor := clGreen end; myquery.Next; end;
….
nun können Sie natürlich weitere Sektionen und Listen definieren, z.B. wie im Programm EasyTodo für Termine.
Am Ende aber auf jeden Fall wichtig,
dayliste.EndUpdate; // um das Zeichnen zu verbergen
sonst sehen Sie nur schwarz ;) heißt, dass Zeichnen der Liste ist damit beendet
Das war es schon, alle Elemente werden dynamisch entsprechend der vorhandenen Datenbankeinträge generiert
Die Events wie z.B. wie OnItemDblClick haben wir ja schon angelegt, nun müssen wir aber das Ereignis noch auswerten und mit Leben erfüllen.
procedure TfrmMeinTag.ImageTextItem1ItemDblClick(Sender: TObject; Item: TCustomItem); begin
da die Namen der Elemente ja eindeutig gekennzeichnet sind, kein Problem
if Copy(Item.Name,1,1)='A' //ermittelt z.B., ob das angeklickte Element eine Ausgabe ist
und mit
DatenbankID:=StrToInt(Copy(Item.Name,3,length(Item.Name)))
bekommen Sie auch den ID-Wert des Datenbankeintrages, den das Listenelement repräsentiert
Diesen können Sie dann Auswerten, den entsprechenden Datensatz ansteuern und dann eben die gewünschte Maßnahme durchführen
Dieses einfache, verkürzte Beispiel hat Ihnen gezeigt, wie man sehr schnell, optisch ansprechende, flexible und moderne Listen dynamisch generiert, die Ihrem Programm Pepp verleihen, Sie müssen sich als nicht mehr mit langweiligen Standard – Listboxen begnügen.
Viel Spaß beim Testen und Experimentieren.