Home » Tutorials » Object Pascal/RTL » Visual Live Bindings

Visual Live Bindings

Verbindungen mit eigenen Objekten

Wir haben nun gesehen, wie man Verbindungen zu GUI-Komponenten und zu Datenbanken herstellt. Aber wie sieht es mit eigenen Objekten bzw. Listen von Objekten aus, die ich zur Laufzeit erzeugt habe und die nicht aus einer Datenbank stammen?
Natürlich gibt es auch dafür eine Lösung. Zunächst die Variante mit einem einzelnen Objekt.
Zur Anbindung an eine Datenbank haben wir eine Komponente vom Typ TBindSourceDB verwendet. Nun kommt TAdapterBindSource zum Einsatz. Als erstes benötigen wir aber überhaupt ein Objekt, dessen Inhalt wir darstellen wollen. Erzeugen wir also eine neue Anwendung (egal ob VCL oder FireMonkey) und legen eine neue Unit „Book“ an, die ein einzelnes Buch repräsentieren soll:

unit book;

interface

type
  TBook = class
  private
    FAuthor: String;
    FTitle: String;
    FPrice: Double;
  public
    property Author: String read FAuthor write FAuthor;
    property Title: String read FTitle write FTitle;
    property Price: Double read FPrice write FPrice;
    constructor Create(const Author, Title: String; Price: Double); virtual;
  end;

implementation

{ TBook }

constructor TBook.Create(const Author, Title: String; Price: Double);
begin
  FAuthor := Author;
  FTitle := Title;
  FPrice := Price;
end;

end.

In der Unit unseres Hauptfensters benötigen wir nun ein Feld, das ein Buchobjekt enthält:

type
  TForm1 = class(TForm)
  private
    { Private-Deklarationen }
    MyBook: TBook;
  public
    { Public-Deklarationen }
  end;

Nun setzen wir eine TAdapterBindSource-Komponente auf das Fenster. Diese lässt sich nun nicht per Drag&Drop mit Inhalt befüllen. Hier muss etwas implementiert werden – und zwar im Ereignis OnCreateAdapter, das im Objektinspektor zu finden ist. In dieser Methode erzeugen wir zunächst eine TBook-Instanz (das OnCreate-Ereignis des Formulars ist zu spät dafür, der Adapter wird vorher erzeugt) und anschließend einen Adapter:

procedure TForm1.AdapterBindSource1CreateAdapter(Sender: TObject;
  var ABindSourceAdapter: TBindSourceAdapter);
begin
  MyBook := TBook.Create('Hans Maier', 'Was Wissenswertes', 49.90);
  ABindSourceAdapter := TObjectBindSourceAdapter<TBook>.Create(self, MyBook);
end;

Die Parameter von TObjectBindSourceAdapter.Create sind zunächst der Eigentümer des Adapters (in unserem Fall „self“, also das Formular) und anschließend die Buch-Instanz. Es gibt noch einen dritten Parameter namens „AOwnsObject“, der standardmäßig true ist. true bedeutet, dass das Objekt die Freigabe der Buch-Instanz übernimmt, wenn es selbst freigegeben wird.
Nun fehlt noch eine GUI-Komponente zur Darstellung des Buchs. Dafür verwenden wir ein TStringGrid. Sobald wir in den LiveBindings-Designer gewechselt haben, sehen wir, dass zwei Elemente zu sehen sind: AdapterBindSource1 und StringGrid1. Beide zeigen als Property nur ein Sternchen an. Woher soll der Adapter auch wissen, welche Felder ein TBook enthält – er erfährt schließlich erst zur Laufzeit, dass er ein Buch darstellen soll. Deshalb verbinden wir erst einmal die beiden Sternchen miteinander:

Wir starten die Anwendung – und sehen das Buch im StringGrid.
Nun wollen wir aber den Titel des Buches in einem eigenen Edit-Feld anzeigen. Spätestens jetzt benötigen wir im LiveBindings-Designer die Properties des Buchs. Dabei hilft uns die Komponente TDataGeneratorAdapter weiter. Sie ähnelt der Komponente TPrototypeBindSource, die wir im Datenbank-Beispiel verwendet haben.
Über einen Doppelklick auf die DataGeneratorAdapter-Komponente (oder Rechtsklick – Feld-Editor) können wir Felder hinzufügen. Das machen wir und achten dabei darauf, dass diese Felder genauso heißen wie die Properties von TBook und auch den gleichen oder einen kompatiblen Datentyp haben:

Nun müssen wir die Komponente DataGeneratorAdapter noch mit der AdapterBindSource verbinden. Dazu gehen wir in den Objektinspektor und wählen die Komponente AdapterBindSource1 aus. Diese hat eine Eigenschaft „Adapter“. Hier selektieren wir den DataGeneratorAdapter1.
Ein Blick in den LiveBindings-Designer: DataGeneratorAdapter1 ist nun Teil von AdapterBindSource1 und zeigt die einzelnen Properties an:

Außerdem zeigt das StringGrid nun auch im Design-Modus Daten an, die der DataGeneratorAdapter erzeugt hat – nicht erst zur Laufzeit des Programms. Nun können wir weitere Komponenten auf dem Formular platzieren und mit einzelnen Properties verbinden wie wir es in den vorangegangenen Beispielen bereits getan haben.

Eine Liste von Objekten

Nun wollen wir aus dem einzelnen Buch eine Liste von Büchern machen. Das Feld in Form1 muss statt einer TBook-Instanz also eine ganze Liste aufnehmen. Deshalb ändern wir es:

MyBooks : TObjectList;

Entsprechend muss in der OnCreateAdapter-Methode eine Liste an Büchern erzeugt werden. Außerdem kommt statt des TObjectBindSourceAdapter ein TListBindSourceAdapter zum Einsatz. Das sieht dann so aus:

procedure TForm1.AdapterBindSource1CreateAdapter(Sender: TObject;
  var ABindSourceAdapter: TBindSourceAdapter);
begin
  MyBooks := TObjectList.Create;
 
  MyBooks.Add(TBook.Create('Hans Maier', 'Was Wissenswertes', 49.90));
  MyBooks.Add(TBook.Create('Erna Schmidt', 'Meine Rezepte', 19.99));
 
  ABindSourceAdapter := TListBindSourceAdapter.Create(self, MyBooks);
end;

Alles andere bleibt wie oben beschrieben. Bei mehreren Objekten ist es natürlich sinnvoll, noch einen Navigator hinzuzufügen – dazu Rechtsklick AdapterBindSource1 – „Navigator hinzufügen“. Dadurch lassen sich auch ohne weiteren Code zusätzliche Bücher in die Liste einfügen, die bei Programmende aber natürlich auch wieder verloren gehen, sofern nicht zusätzlicher Code zum Speichern in einer Datei geschrieben wird.

Download Beispielprojekt