Autor Beitrag
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19339
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 29.08.11 02:00 
Hallo,

ich möchte euch hier ein paar Aspekte der mit Delphi XE 2 kommenden LiveBindings™ zeigen.

Vorweg: Die Vorstellung von Details zu den bereits veröffentlichten Features ist von Embarcadero autorisiert. Im Rahmen dessen bin ich auch gern bereit Fragen zu beantworten soweit möglich.

Nun zur Sache. ;-) Ich benutze im Beispiel einfach einmal eine der mitgelieferten Datenbanken. Diese beinhaltet eine Liste von Ereignissen mit unter anderem einem Namen und einem Foto. Diese möchte ich jetzt anzeigen sowie durch die Datensätze navigieren. Zudem möchte ich eine eigene Klasse ansteuern, die die Formularüberschrift mit der aktuellen Recordnummer füttert.

Ich belasse im Beispiel explizit die Standardbezeichner, um keine unnötige Verwirrung zu stiften. Ich habe eine neue FireMonkey Anwendung erstellt. Auf das Formular kommt links oben ein Label zur Anzeige des Namens des Events, die Recordnummer des aktuellen Eintrags in eines rechts oben, darunter das Bild des Events. Darunter dann noch eine Fortschrittsanzeige zur Visualisierung des Fortschritts beim Blättern durch die Datenbank sowie ein Navigator. Das Formular sieht im Designer fertig so aus:

[url=www.sj-berlin.de/ser...aBindingProject.png]user defined image[/url]

Jetzt benötige ich zunächst die Datenbankverbindung, dafür benutze ich ein TClientDataSet verbunden zu einer TDataSource. Dem ClientDataSet gebe ich den FileName, in diesem Fall die Datei events.xml. Die TDataSource bekommt als DataSet noch das TClientDataSet und dieses wird auf Active gesetzt.

Nun kennen die LiveBindings™ automatisch die Felder der Datenbank. Ich möchte jetzt die Felder der Datenbank mit meinen Komponenten verknüpfen. Dafür klicke ich mit rechts auf das Label links oben um den Eventnamen damit zu verknüpfen:

user defined image

Es wird die Auswahl der verfügbaren Datenquellen und Datenbankfelder angezeigt. Im Hintergrund sieht man bereits die automatisch neu erstellte TBindingsList. Zu der komme ich gleich.

user defined image

Für die Verknüpfung mit den Datenbankfeldern wird auch automatisch eine TBindScopeDB Komponente erstellt. Auf die selbe Weise verknüpfe ich auch das Bild. Beim TBindNavigator genügt es die TBindScopeDB Komponente an BindScope zuzuweisen.

Nun verknüpfe ich noch den aktuellen Wert der ProgressBar sowie den maximalen Wert mit den Werten des ClientDataSets. Das geht nicht ohne ein wenig Handarbeit. Ich erstelle diesmal eine neue Datenbindung über eine TBindExpression, die ich manuell definieren kann:

user defined image
user defined image

Dort gibt es Control* und Source*, ersteres definiert das zu steuernde Control, letzteres das Control, von dem die Daten stammen. In diesem Fall wird die ProgressBar kontrolliert, und zwar dessen Wert Value bzw. im zweiten Fall Max. Die Daten kommen vom ClientDataSet. Nämlich aus RecNo bzw. RecordCount.

user defined image

Genauso binde ich auch noch Label2.Text an ClientDataSet1.RecNo. Soweit so gut. Wenn man dieses Programm ausführt, wird allerdings die ProgressBar nicht verändert. Warum? Nun, das liegt daran, dass die Datenbindung nicht weiß, dass die Eigenschaften RecNo und RecordCount einen neuen Wert bekommen haben. Daher werden die gebundenen Elemente nicht aktualisiert. Es reicht also mitzuteilen, dass diese Datenbindungen aktualisiert werden müssen. Dafür benutze ich das Event OnAfterScroll des ClientDataSets:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
procedure TForm114.ClientDataSet1AfterScroll(DataSet: TDataSet);
begin
  TBindings.Notify(ClientDataSet1, 'RecNo');
  TBindings.Notify(ClientDataSet1, 'RecordCount');
end;
Dafür wird die Unit System.Bindings.Helper benötigt. Das genügt bereits. Jetzt funktioniert die kleine Demo bereits. Und das mit zwei Zeilen Code. ;-)

user defined image

Wenn ihr die Möglichkeit habt, schaut doch auf der RAD Studio XE 2 World Tour vorbei um weitere spannende Details zu sehen. ;-)
www.embarcadero.com/world-tour
Einloggen, um Attachments anzusehen!


Zuletzt bearbeitet von jaenicke am Mo 29.08.11 10:25, insgesamt 5-mal bearbeitet

Für diesen Beitrag haben gedankt: Christian S., Dude566, Marc., Narses
jaenicke Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19339
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 29.08.11 02:01 
Jetzt zeige ich noch kurz, dass man auf diese Weise natürlich auch eigene Klassen ansteuern kann. Hier ein kleines Beispiel, das die aktuelle Recordnummer auch in die Formularüberschrift schreibt:

// EDIT:
Da das wohl noch nicht klar genug formuliert war:
Es geht hier nicht darum die Überschrift zu aktualisieren, das ist nur ein Beispiel. Mir ist halt als erstes das für ein abgeschlossenes kleines Beispiel eingefallen.
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
type
  TUpdateFormCaption = class(TComponent)
  private
    FFormCaption: string;
    FForm: TForm;
    procedure SetFormCaption(const Value: string);
  public
    constructor Create(AForm: TForm);
    property FormCaption: string read FFormCaption write SetFormCaption;
  end;

  TForm114 = class(TForm)
  // ...
  public
    FTest: TUpdateFormCaption;
    FTestBindExpression1: TBindExpression;
  end;

var
  Form114: TForm114;

implementation

{$R *.fmx}

procedure TForm114.ClientDataSet1AfterScroll(DataSet: TDataSet);
begin
  TBindings.Notify(ClientDataSet1, 'RecNo');
  TBindings.Notify(ClientDataSet1, 'RecordCount');
end;

{ TMyLittleClass }

procedure TForm114.FormCreate(Sender: TObject);
begin
  FTest := TUpdateFormCaption.Create(Self);
  FTestBindExpression1 := TBindExpression.Create(Self);
  FTestBindExpression1.ControlComponent := FTest;
  FTestBindExpression1.ControlExpression := 'FormCaption';
  FTestBindExpression1.SourceComponent := ClientDataSet1;
  FTestBindExpression1.SourceExpression := 'RecNo';
  FTestBindExpression1.Active := True;
end;

{ TUpdateFormCaption }

constructor TUpdateFormCaption.Create(AForm: TForm);
begin
  inherited Create(AForm);
  FForm := AForm;
end;

procedure TUpdateFormCaption.SetFormCaption(const Value: string);
begin
  FFormCaption := Value;
  FForm.Caption := Value;
end;
Hier weise ich die Eigenschaften einfach nur manuell zu. Das ist also alles kein Hexenwerk. ;-)

Da die Benachrichtigung für die Bindings bereits existiert, muss da auch nichts weiter passieren. Die beiden Zeilen in OnAfterScroll genügen um die ProgressBar, das Label und dieses eigene Objekt zu aktualisieren.


Zuletzt bearbeitet von jaenicke am Mi 31.08.11 04:41, insgesamt 1-mal bearbeitet

Für diesen Beitrag haben gedankt: Dude566
jaenicke Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19339
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 29.08.11 02:12 
Als letztes zeige ich noch wie die erzeugten Datenbindungen in der Übersicht aussehen:

[url=www.sj-berlin.de/ser...indingsOverview.png]user defined image[/url]

Hier seht ihr auch wofür die Kategorien bei den einzelnen Bindings sind. Durch diese Bezeichnungen können die Bindings sortiert werden, damit man bei umfangreicheren GUIs die Übersicht behält.

Natürlich funktioniert das unter 64-Bit genauso:

user defined image

Es gibt auch die Möglichkeit in die Verarbeitung manuell einzugreifen. Dafür gibt es z.B. ein Event, wenn ein neuer Wert einer Expression zugewiesen wird. In dem Event ist z.B. auch die Änderung des Wertes möglich. Das habe ich mir aber selbst noch nicht genauer angeschaut.

Für diesen Beitrag haben gedankt: Dude566
Lemmy
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 792
Erhaltene Danke: 49

Windows 7 / 10; CentOS 7; LinuxMint
Delphi 7-XE10.1, VS 2015
BeitragVerfasst: Mo 29.08.11 06:41 
Hi Sebastian,

vielen herzlichen Dank!!

Lemmy
mkinzler
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 4106
Erhaltene Danke: 13


Delphi 2010 Pro; Delphi.Prism 2011 pro
BeitragVerfasst: Mo 29.08.11 18:29 
Das funktioniert natürlich nicht nur bei FireMonkey-Anwendungen, sondern wurde auch in die VCL eingeführt.

_________________
Markus Kinzler.
Dude566
ontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic starofftopic star
Beiträge: 1592
Erhaltene Danke: 79

W8, W7 (Chrome, FF, IE)
Delphi XE2 Pro, Eclipse Juno, VS2012
BeitragVerfasst: Di 30.08.11 18:32 
Sind die Fenster eigentlich nur bei Firemonkey Projekten schwarz oder welchen Hintergrund hat das? :lupe:

_________________
Es gibt 10 Gruppen von Menschen: diejenigen, die das Binärsystem verstehen, und die anderen.
mkinzler
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 4106
Erhaltene Danke: 13


Delphi 2010 Pro; Delphi.Prism 2011 pro
BeitragVerfasst: Di 30.08.11 18:36 
Nein. sie sehen nur im Formulardesigner so aus, möglicherweise um sofort zu sehen, ob es sich um eine VCL oder FMX Anwendung handelt.

_________________
Markus Kinzler.

Für diesen Beitrag haben gedankt: Dude566
Dude566
ontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic starofftopic star
Beiträge: 1592
Erhaltene Danke: 79

W8, W7 (Chrome, FF, IE)
Delphi XE2 Pro, Eclipse Juno, VS2012
BeitragVerfasst: Di 30.08.11 18:39 
Ja ich meinte ja auch nur im Designer, aber eben um Firemonkey und VCL zu unterscheiden.

_________________
Es gibt 10 Gruppen von Menschen: diejenigen, die das Binärsystem verstehen, und die anderen.
Stevie
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 85

Windows 7
Delphi XE Professional
BeitragVerfasst: Di 30.08.11 21:53 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Das genügt bereits. Jetzt funktioniert die kleine Demo bereits. Und das mit zwei Zeilen Code. ;-)

Wo ist da jetzt der Fortschritt? Ging schon seit (seit wann gibt es die DB Controls und TClientDataset in Delphi?)...

Die 2 Zeilen Code bis Delphi XE sähen übrigens so aus:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
procedure TForm114.ClientDataSet1AfterScroll(DataSet: TDataSet);
begin
  ProgressBar1.Value := ClientDataSet1.RecNo;
  ProgressBar1.Max := ClientDataSet1.RecordCount;
end;


Übrigens mit dem Vorteil, dass mich der Compiler anmeckert, falls ich mich verschreibe.

Sieht für mich irgendwie wie ein Ersatz für die DB Controls in FMX aus.

_________________
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin
jaenicke Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19339
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 30.08.11 22:48 
user profile iconStevie hat folgendes geschrieben Zum zitierten Posting springen:
Sieht für mich irgendwie wie ein Ersatz für die DB Controls in FMX aus.
Das ist es dort auch, ja. Die gibt es dort nicht.

Die Anbindung anderer Objekte als TDBxxx (z.B. eigene Controls) sehe ich aber in XE nicht ohne Quelltext. :gruebel:
(Auch wenn ich noch nicht weiß, ob ich die Datenanbindung tatsächlich dafür nutzen werde, das tue ich z.B. in C# auch nicht.)
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Mi 31.08.11 00:12 
So wie ich das sehe, ist das die offensichtliche Verwendung von RTTI, die ja jetzt ordentlich funktioniert.

Die Umsetzung des Ganzen in der IDE ist ziemlich gut gemacht; allerdings finde ich den Code dazu etwas sehr länglich. Da extra ein Objekt für zu konfigurieren finde ich etwas seltsam, aber die Helper-Funktion dazu kann man sich ja selber schreiben.

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
Stevie
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 85

Windows 7
Delphi XE Professional
BeitragVerfasst: Mi 31.08.11 00:22 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Die Anbindung anderer Objekte als TDBxxx (z.B. eigene Controls) sehe ich aber in XE nicht ohne Quelltext. :gruebel:

Hab ich auch nicht gesagt. Da es aber nunmal in der VCL die DB Controls gibt, seh ich keine Veranlassung, dort diese LiveBinding Geschichte zu benutzen (zumal ich irgendwo gelesen habe, dass es diese "Mit DB-Feld verknüpfen..." Sache nur unter FMX gibt, aber da kannst du sicher was zu sagen)

user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
So wie ich das sehe, ist das die offensichtliche Verwendung von RTTI, die ja jetzt ordentlich funktioniert.

Öh, ja, trotzdem ist die RTTI nach wie vor string basiert, was das Finden eines Bezeichners angeht und wird erst, wie der Name schon sagt, erst zur Laufzeit ausgewertet. Was das an Fehlerpotenzial enthält, brauch ich wohl nicht zu erläutern. Funktioniert das eigentlich noch, wenn ich die RTTI ausschalte? Ich hätt Besseres erwartet.

user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
Die Umsetzung des Ganzen in der IDE ist ziemlich gut gemacht; allerdings finde ich den Code dazu etwas sehr länglich. Da extra ein Objekt für zu konfigurieren finde ich etwas seltsam, aber die Helper-Funktion dazu kann man sich ja selber schreiben.

Ich dachte mir nur: "WTF, wat nen Haufen Code, nur um ne Caption zu befüllen?!"

_________________
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin
jaenicke Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19339
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 31.08.11 04:43 
user profile iconStevie hat folgendes geschrieben Zum zitierten Posting springen:
Geschichte zu benutzen (zumal ich irgendwo gelesen habe, dass es diese "Mit DB-Feld verknüpfen..." Sache nur unter FMX gibt, aber da kannst du sicher was zu sagen)
Richtig, das ist FireMonkey only. Genau aus dem Grund, dass es in der VCL die DB-Komponenten gibt. Das ist dort auch nicht als Ersatz gedacht.

Ich schreibe wohl besser auch noch etwas was die Bindings in der VCL angeht.

user profile iconStevie hat folgendes geschrieben Zum zitierten Posting springen:
Ich dachte mir nur: "WTF, wat nen Haufen Code, nur um ne Caption zu befüllen?!"
Oh, sorry, ich dachte das wäre klar genug geschrieben, dass das nur ein Beispiel sein sollte um zu zeigen, dass auch eigene Objekte so ansteuerbar sind. :shock: Ich habe das noch einmal explizit dazu geschrieben.
Sinspin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1336
Erhaltene Danke: 119

Win 10
RIO, CE, Lazarus
BeitragVerfasst: Mi 31.08.11 13:12 
Diese Technik ist aber nur für Komponenten gedacht die sonst nichts mit Datenbanken am Hut haben? Denn, wäre es anders wäre es ein Schritt in die Steinzeit.
Man muss sich ja nur mal den Irrsinn vorstellen wenn man eine komplexe Eingabemaske hat und für jedes Edit so einem Murks machen müsste.
Eins verstehe nicht, wenn eh bekannt ist das ein bestimmtes Property einem Tabellenfeld zugeordnet ist warum man dann noch manuell benachrichtigen muss das es geändert werden muss. Denn jedes DataSet und jede DataSource ist in der Laage alle interessenten über Änderungen zu informieren. Sogar jedes einzelne Tabellenfeld feuert Ereignisse wenn es sich ändert.

Wie es scheint gibt es immernoch keinen ordentlichen Aufbewahrungsort für nichtvisuelle Komponenten. Was bedeutet das die mir immernoch meine Formulare zumüllen. Gerade wenn ich mir überlege das fürs Livebinding jedesmal eine weitere nicht visuelle Komponente erstellt wird, wird das ganz schön schnell unübersichtlich.

_________________
Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
jaenicke Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19339
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 31.08.11 13:55 
user profile iconSinspin hat folgendes geschrieben Zum zitierten Posting springen:
Eins verstehe nicht, wenn eh bekannt ist das ein bestimmtes Property einem Tabellenfeld zugeordnet ist warum man dann noch manuell benachrichtigen muss das es geändert werden muss.
Das ist nicht nötig, ich wollte RecNo und RecordCount auslesen, nur da musste ich manuell benachrichtigen. ;-)
Stevie
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 85

Windows 7
Delphi XE Professional
BeitragVerfasst: Mi 31.08.11 13:57 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconSinspin hat folgendes geschrieben Zum zitierten Posting springen:
Eins verstehe nicht, wenn eh bekannt ist das ein bestimmtes Property einem Tabellenfeld zugeordnet ist warum man dann noch manuell benachrichtigen muss das es geändert werden muss.
Das ist nicht nötig, ich wollte RecNo und RecordCount auslesen, nur da musste ich manuell benachrichtigen. ;-)

Und genau das ist eins der Hauptprobleme mit der aktuellen Implementierung. Die Benachrichtigungen über Property Änderungen gehen nicht von dem Objekt selber aus. Somit ist immer extra Code in entsprechenden Events nötig, um dies abzugreifen.

_________________
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin