Delphi, LiveBindings de A à ... Épisode 1

Pourquoi utiliser les LiveBindings ?

Serge Girard

L'objectif de cette première partie est de comprendre pourquoi les LiveBindings sont apparus et ce qu'ils peuvent nous apporter.

Commentez

- Titre : Delphi, LiveBindings de A à ... Épisode 1

- Auteur : Serge Girard

- Parution : 20 mai 2017

- Mise à jour : 22 mai 2017

- Public visé :

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2017 Serge Girard. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Introduction

- II. Définition rapide

- III. Une utilisation simple

- III-1. La méthode « à l'ancienne »

- III-2. En FMX

- III-2-1. Revenons à la formule

- III-2-2. CustomFormat

- III-2-3. Qui est ce Owner et pourquoi l'utiliser

- III-2-4. Comment faire pour vérifier la formule ?

- III-2-5. Comment se passer des liaisons rapides ?

- III-2-5-a. Première étape

- III-2-5-b. Deuxième étape

- III-2-5-c. Troisième étape : le remplissage des premières propriétés

- III-2-5-d. Quatrième étape : les expressions

- III-2-6. Que constate-t-on ?

- III-3. Et si on appliquait ça au programme VCL ?

- III-3-1. Lien rapide

- III-3-2. Lien manuel

- IV. Conclusion de cet épisode

- V. Notes

I - Introduction

La traduction littérale du mot (selon googletrad, de l'anglais vers le français) : « fixations en direct » n'est pas forcément très parlante !

Si nous remplaçons le terme de « fixations » par « liaisons » nous commençons à y voir un peu plus clair. Reste à répondre à la question « liaisons de quoi ? » Pour généraliser, je répondrai : de toute propriété d'un composant, mais avec un bémol, d'un composant avec des propriétés observables. Je reprendrai plus tard cette notion « d'observabilité ».

Les LiveBindings nous ont été proposés dès la version XE2 de RAD Studio (Delphi et C++ Builder), c'est-à-dire en même temps que FMX et inclus aussi à la VCL(1). Une des raisons essentielles de cette introduction, du moins pour FMX, était qu'il n'y a aucun composant lié aux sources de données ! Bien sûr il était possible, par code, de lier les valeurs aux composants, mais plus il y a de code, plus il y a de sources d'erreurs possibles. Les concepteurs ont donc décidé de nous « simplifier » la tâche.

Lors de la version XE3, les versions professionnelles et plus se sont vu octroyer un concepteur visuel de liaisons qui couvre la plupart des besoins d'une application « classique ». Le piège de la facilité des liaisons dites « rapides » est que si elles couvrent au moins quatre-vingts pour cent des besoins, on se retrouve quelquefois dans des impasses qu'une liaison plus « manuelle » pourrait régler. Malheureusement, peu de documentation est disponible. L'objectif principal de cette suite de tutoriels est d'essayer de faire le tour des possibilités de ces liaisons.

II - Définition rapide

Le LiveBinding est un mécanisme (framework) de RAD Studio qui permet d'associer les propriétés d'un objet à une expression sous la forme d'une chaîne. L'expression, évaluée lors de l'exécution du programme (runtime), peut être une propriété de cet objet, d'un autre objet, ou une formule plus complexe incluant des propriétés d'objets, des constantes littérales, des opérateurs ou des méthodes.

À retenir :

1. Un LiveBinding est un objet contenant une ou plusieurs expressions ;

2. Les expressions sont des phrases (formules, chaînes) qui sont évaluées par l'évaluateur d'expressions ;

3. En pratique, les LiveBindings invoquent d'eux-mêmes le moteur d'évaluation pour interpréter les expressions.

III - Une utilisation simple

Plutôt qu'un long préambule, passons à une démonstration. L'objectif du programme est de déplacer une balle avec un curseur. La forme principale ne contiendra qu'un TShape de forme ronde et un TTrackbar. En faisant glisser le curseur, la balle se déplacera au-dessus.

L'application ne risque pas d'être inscrite dans les annales, mais elle est suffisante pour la présentation.

III-1 - La méthode « à l'ancienne »

Design de la forme

(cliquez ici pour aggrandir l'image)

Avec les anciennes versions, nous utiliserons l'événement OnChange du composant TTrackbar pour réaliser le déplacement.

Unité VCL

unit U_Prog1;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.ComCtrls;

type
TForm8 = class(TForm)
TrackBar1: TTrackBar;
Shape1: TShape;
procedure TrackBar1Change(Sender: TObject);
private
{ Déclarations privées }
public
{ Déclarations publiques }
end;

var
Form8: TForm8;

implementation

{$R *.dfm}

procedure TForm8.TrackBar1Change(Sender: TObject);
var percent : Double;
posCurseur: integer;
begin
// Méthode "Classique", Calcul décomposé pour les besoins de l'explication
// calcul du pourcentage sur la barre
Percent:=TrackBar1.Position / TrackBar1.Max;
// Calcul en pixels, Arrondi nécessaire
PosCurseur:=Round(TrackBar1.Width*Percent);
// Positionnement exact du cercle rouge
Shape1.Left:=TrackBar1.Left+posCurseur-(Shape1.Width div 2);
end;

end.

Pour que vous puissiez reproduire l'exemple, je vous propose aussi le source de la fiche. En fait, ce n'est pas aussi innocent que vous pourriez le penser, ce source nous servant par la suite comme point de comparaison.

DFM

object Form8: TForm8
Left = 0
Top = 0
Caption = 'D'#233'placer la balle'
ClientHeight = 117
ClientWidth = 447
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object Shape1: TShape
Left = 0
Top = 8
Width = 40
Height = 41
Brush.Color = clRed
Pen.Color = clRed
Shape = stCircle
end
object TrackBar1: TTrackBar
AlignWithMargins = True
Left = 20
Top = 69
Width = 407
Height = 45
Margins.Left = 20
Margins.Right = 20
Align = alBottom
TabOrder = 0
OnChange = TrackBar1Change
ExplicitLeft = 8
ExplicitTop = 112
ExplicitWidth = 431
end
end

III-2 - En FMX

Mise en garde aux détenteurs d'une version starter

Malheureusement pour les détenteurs de cette version le concepteur visuel de liens n'est pas disponible (ainsi que les raccourcis y faisant accès).

Pour eux, seule la méthode « manuelle » sera accessible !

Ces points ou visuels non accessibles seront indiqués par un astérisque (*).

Pas de grand changement dans la présentation, seuls changements visuels notables :

- le TShape devient un TCircle ;

- le TTrackBar n'a pas tout à fait la même présentation ;

- et, bien sûr, pour les non habitués à FMX, cela peut surprendre que le cadre de la forme Windows ait disparu .

(cliquez ici pour aggrandir l'image)

On pourrait, bien sûr, coder le même événement OnChange de la TTrackbar mais, et c'est quand même l'objectif, nous allons passer par les LiveBindings.

Deux possibilités s'offrent à nous :

- passer par l'expert (concepteur visuel)(2) ;

- avoir une démarche composant, en plaçant sur la forme, un TBindingsList.

Comme il s'agit dans un premier temps d'une introduction, nous utiliserons la première solution. Un petit clic droit sur la forme et la sélection de l'option « Lier visuellement... »* nous ouvre, en bas de l'écran, une fenêtre de conception visuelle.

Toutefois, si l'on voit apparaître la propriété Value pour le composant TrackBar1, pour Circle1 aucune propriété n'est accessible ! Une seconde étape est donc nécessaire : savoir quelle est la propriété que nous devons modifier et, bien évidemment, la voir apparaître dans le concepteur.

Point de propriété Left avec les composants FMX, celle-ci étant remplacée par une propriété Position.X. Un clic sur les … positionnés sous le nom du composant nous affiche une liste des membres pliables.

Liste des membres liables *

(cliquez ici pour aggrandir l'image)

Après validation, nous pourrons, avec la souris, lier les deux propriétés, ce qui sera représenté par une flèche.

Conception visuelle *

(cliquez ici pour aggrandir l'image)

Que s'est-il passé ?

Sur la forme, un nouveau composant est apparu : un TBindingsList et ce dernier a même déjà un élément : LinkControlToPropertyPositionX (qui fait partie du groupe des liaisons rapides).

Les possesseurs de la version starter auront certainement compris qu'il leur faut donc déposer « manuellement » un TBindingsList et ajouter, grâce au menu contextuel, un TLinkFieldControlToProperty et remplir les mêmes propriétés renseignées par le concepteur visuel.

Bien, c'est lié, mais où mettre les calculs ?

À ce stade on peut, bien sûr, exécuter le programme, mais le comportement ne sera pas celui souhaité.

Intéressons-nous maintenant à l'inspecteur de propriétés et plus particulièrement à ce fameux élément.

Propriétés du lien

(cliquez ici pour aggrandir l'image)

On y retrouve :

- le nom du composant qui est concerné (Component) ;

- le nom de la propriété concernée (ComponentProperty) ;

- le nom du contrôle effectuant la liaison (Control).

Juste en dessous de cette dernière propriété, il y a CustomFormat. Pour cette dernière nous indiquerons notre calcul, selon la formule suivante :

Formule

Position.X + Value*Width/Max - Owner.Circle1.Width/2

Nous pouvons maintenant compiler et tester le programme et nous observerons le même comportement que le précédent.

Je reviendrai sur la formule un peu plus tard, étudions d'abord les deux sources :

FMX Code Source

unit UFMX_Prog1;

interface

uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
FMX.Controls.Presentation, FMX.StdCtrls, FMX.Objects, Data.Bind.EngExt,
Fmx.Bind.DBEngExt, System.Rtti, System.Bindings.Outputs, Fmx.Bind.Editors,
Data.Bind.Components;

type
TForm8 = class(TForm)
Circle1: TCircle;
TrackBar1: TTrackBar;
BindingsList1: TBindingsList;
LinkControlToPropertyPositionX: TLinkControlToProperty;
private
{ Déclarations privées }
public
{ Déclarations publiques }
end;

var
Form8: TForm8;

implementation

{$R *.fmx}

end.

Surprise ? Pas une seule ligne de code et pourtant, cela fonctionne ! Où est passé notre calcul ? On le retrouve dans le source de la forme, c'est-à-dire dans le fichier d'extension .fmx correspondant :

Fiche FMX

object Form8: TForm8
Left = 0
Top = 0
Caption = 'Jeu de balle'
ClientHeight = 123
ClientWidth = 549
FormFactor.Width = 320
FormFactor.Height = 480
FormFactor.Devices = [Desktop]
DesignerMasterStyle = 0
object Circle1: TCircle
Fill.Color = claRed
Position.Y = 24.000000000000000000
Size.Width = 40.000000000000000000
Size.Height = 50.000000000000000000
Size.PlatformDefault = False
Stroke.Color = claRed
end
object TrackBar1: TTrackBar
Align = Bottom
CanParentFocus = True
Orientation = Horizontal
Margins.Left = 20.000000000000000000
Margins.Right = 20.000000000000000000
Margins.Bottom = 10.000000000000000000
Position.X = 20.000000000000000000
Position.Y = 94.000000000000000000
Size.Width = 509.000000000000000000
Size.Height = 19.000000000000000000
Size.PlatformDefault = False
TabOrder = 1
end
object BindingsList1: TBindingsList
Methods = <>
OutputConverters = <>
Left = 76
Top = 5
object LinkControlToPropertyPositionX: TLinkControlToProperty
Category = 'Liaisons rapides'
Control = TrackBar1
Track = False
Component = Circle1
ComponentProperty = 'Position.X'
CustomFormat = 'Position.X + Value*Width/Max - Owner.Circle1.Width/2'
end
end
end

Donc, effectivement, pas de code direct.

III-2-1 - Revenons à la formule

Bien, le calcul en soi est déjà expliqué dans le source précédent (partie VCL), mais qu'est-ce que ce CustomFormat ? D'où vient ce Owner.Circle1 ? Comment fait-on pour contrôler cette formule ? Questions on ne peut plus légitimes.

III-2-2 - CustomFormat

Je vais d'abord citer la définition faite par Embarcadero :

« LiveBindings est un framework basé sur des expressions, ce qui signifie qu'il utilise des expressions de liaison pour lier des objets à d'autres objets, ou à des champs d'ensemble de données. »

Expressions, le mot est lâché ! De fait, il y en a de deux types :

- les expressions qui vont évaluer la valeur à partir du contrôle source, en l'occurrence une propriété de ce dernier ;

- les expressions qui vont modifier la valeur entrée avant de la stocker dans le contrôle source.

Nous ne nous intéresserons qu'au premier type d'expression qui correspond à CustomFormat (pour mémoire, le second type correspond à CustomParse).

Cette expression peut contenir des calculs mais pas que ! On pourra utiliser quelques méthodes prédéfinies de chaîne telles qu'UpperCase, LowerCase, SubString, de formatage telles que Format, FormatDateTime, mais aussi de petites fonctions de test comme IfAll, IfAny, IfThen.

Bien sûr, qui dit méthodes prédéfinies dit que l'on peut aussi écrire et recenser ses propres méthodes, mais ce n'est pas le sujet de cet épisode.

III-2-3 - Qui est ce Owner et pourquoi l'utiliser

Dans notre cas, Owner correspond à la fiche Form8. On l'utilise pour pouvoir atteindre l'objet Circle1 et donc, par la suite, sa propriété Width. Vous me rétorquerez que pourtant, on n'en a pas besoin pour les propriétés de TrackBar1. C'est exact, car la formule s'applique au propriétaire de la liaison (le contrôle source) et il n'y a donc pas besoin de préciser comment y accéder.

III-2-4 - Comment faire pour vérifier la formule ?

C'est là qu'en général, on commence à se fâcher avec les concepteurs de cet éditeur de liens.

Je vous propose de double-cliquer sur le composant Bindingslist1. Nous obtenons alors une fenêtre listant les objets contenus par ce dernier (pour l'instant un seul),

pas très explicite hélas !

En double-cliquant à nouveau cette fois-ci sur ce lien, classé dans les « Liaisons rapides », on obtient cet écran :

On ira peut-être plus vite en choisissant l'option « Liaison des composants » située dans l'inspecteur d'objets.

Liaison rapide

(cliquez ici pour aggrandir l'image)

Lueur d'espoir ! Il y a bien notre formule et même des boutons qui permettent d'évaluer le contrôle et la source, toutefois (et c'est ce qui fâche le plus) il est impossible de modifier la formule !

Cependant, on peut bien évaluer cette formule.

Pour les besoins de l'image écran et la vérification du calcul, j'ai modifié la position du curseur de mon Trackbar (Value = 50).

III-2-5 - Comment se passer des liaisons rapides ?

Les détenteurs d'une version Starter procéderont de cette manière.

Beaucoup moins aisée à utiliser, c'est pourtant, dans certains cas, une solution à adopter.

Pour ce faire, je vais poser un deuxième cercle sur ma forme (Circle2), que j'ai décidé de colorer en bleu.

III-2-5-a - Première étape

Double-cliquez sur le composant BindingsList1(3), puis utilisez le bouton d'ajout d'un nouveau lien.

On peut aussi utiliser plus rapidement l'option « Nouveau composant LiveBinding » de l'inspecteur d'objets.

III-2-5-b - Deuxième étape

Quel type de lien ? Il est vrai qu'au fil des versions, il y en a beaucoup dont certains sont même devenus obsolètes, mais gardés par souci de compatibilité ascendante.

Types de lien

(cliquez ici pour aggrandir l'image)

Comme il s'agit de créer une liaison entre deux objets, j'ai choisi TBindExpression. J'aurais aussi pu choisir TBindControlValue.

III-2-5-c - Troisième étape : le remplissage des premières propriétés

Encore une fois, il va falloir rester très zen et bien faire attention aux termes, car les noms de propriétés des liaisons rapides et celles que je vais exposer ici sont proches.

(cliquez ici pour aggrandir l'image)

ControlComponent (correspond à Control d'un lien rapide) indiquera le composant dont on veut modifier une ou plusieurs propriétés. Donc, dans notre cas, le cercle bleu.

SourceComponent (correspondant donc à Component d'un lien rapide) indiquera le composant qui fournira la valeur à notre expression. Donc, le TrackBar.

Il ne faudra pas oublier d'indiquer dans quel sens va notre relation. La propriété Direction aura la valeur DirSourceToControl (valeur par défaut).

III-2-5-d - Quatrième étape : les expressions

On peut saisir directement l'expression déjà exposée (III.2.1 ou, et c'est la solution qui permettra de tester les formules saisies, passer par l'écran que nous avons déjà vu plus haut Comment faire pour vérifier la formule ? Donc, cliquons sur l'option « Expressions » de l'inspecteur d'objets et ajoutons notre fameuse formule. Cette fois-ci, l'expression est modifiable !

(cliquez ici pour aggrandir l'image)

III-2-6 - Que constate-t-on ?

Au niveau visuel, il y a une différence : un élément, indiqué par un astérisque, a été ajouté à TrackBar1.

Niveau visuel*

(cliquez ici pour aggrandir l'image)

Attention à la casse de l'expression de contrôle. Pour peu que vous la changiez, vous pourriez vous retrouver avec deux fois le même élément.

Le source de la forme, lui, s'est légèrement étoffé. Normal puisque l'on a ajouté deux éléments.

Nouveau FMX

object Form8: TForm8
Left = 0
Top = 0
Caption = 'Jeu de balle'
ClientHeight = 160
ClientWidth = 549
FormFactor.Width = 320
FormFactor.Height = 480
FormFactor.Devices = [Desktop]
DesignerMasterStyle = 0
object Circle1: TCircle
Fill.Color = claRed
Position.Y = 72.000000000000000000
Size.Width = 40.000000000000000000
Size.Height = 50.000000000000000000
Size.PlatformDefault = False
Stroke.Color = claRed
end
object TrackBar1: TTrackBar
Align = Bottom
CanParentFocus = True
Orientation = Horizontal
Margins.Left = 20.000000000000000000
Margins.Right = 20.000000000000000000
Margins.Bottom = 10.000000000000000000
Position.X = 20.000000000000000000
Position.Y = 131.000000000000000000
Size.Width = 509.000000000000000000
Size.Height = 19.000000000000000000
Size.PlatformDefault = False
TabOrder = 1
OnChange = TrackBar1Change
end
object Circle2: TCircle
Fill.Color = claBlue
Position.Y = 16.000000000000000000
Size.Width = 40.000000000000000000
Size.Height = 50.000000000000000000
Size.PlatformDefault = False
Stroke.Color = claBlue
end
object BindingsList1: TBindingsList
Methods = <>
OutputConverters = <>
Left = 76
Top = 5
object LinkControlToPropertyPositionX: TLinkControlToProperty
Category = 'Liaisons rapides'
Control = TrackBar1
Track = False
Component = Circle1
ComponentProperty = 'Position.X'
CustomFormat = 'Position.X + Value*Width/Max - Owner.Circle1.width/2'
end
object BindExpression1: TBindExpression
Category = 'Expressions de liaison'
ControlComponent = Circle2
SourceComponent = TrackBar1
SourceExpression = 'Position.X + Value * Width/Max - Owner.Circle2.Width/2'
ControlExpression = 'Position.X'
NotifyOutputs = True
Direction = dirSourceToControl
end
end
end

Il ne nous reste plus qu'à exécuter le programme afin de tester son comportement.

Constatation : si le cercle rouge bouge correctement, le bleu lui reste fixe. Il manque donc quelque chose : le moteur des LiveBindings doit être informé qu'il faut entreprendre une action, celle qui se faisait automatiquement avec le lien rapide.

Seule solution : ajouter un bout de code à notre programme. Nous revoilà avec l'événement OnChange de notre TrackBar. Seulement, au lieu d'y indiquer le calcul, nous allons forcer l'évaluateur d'expressions à faire son boulot. Cela se fera via une instruction notifiant au moteur de traiter l'objet.

Voici donc le nouveau source du programme :

Nouveau Source

unit UFMX_Prog1;

interface

uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
FMX.Controls.Presentation, FMX.StdCtrls, FMX.Objects, Data.Bind.EngExt,
Fmx.Bind.DBEngExt, System.Rtti, System.Bindings.Outputs, Fmx.Bind.Editors,
Data.Bind.Components;

type
TForm8 = class(TForm)
Circle1: TCircle;
TrackBar1: TTrackBar;
BindingsList1: TBindingsList;
LinkControlToPropertyPositionX: TLinkControlToProperty;
Circle2: TCircle;
BindExpression1: TBindExpression;
procedure TrackBar1Change(Sender: TObject);
private
{ Déclarations privées }
public
{ Déclarations publiques }
end;

var
Form8: TForm8;

implementation

{$R *.fmx}

procedure TForm8.TrackBar1Change(Sender: TObject);
begin
BindingsList1.Notify(Sender,'');
end;

end.

Conclusion de cette partie : finalement, les liaisons rapides (quand on en a la possibilité) c'est plus simple !

III-3 - Et si on appliquait ça au programme VCL ?

VCL Liaison rapide*

(cliquez ici pour aggrandir l'image)

Selon le même principe, j'ajoute un cercle bleu et, fort de l'expérience sur les liaisons rapides FMX, j'ajoute les deux propriétés que je veux contrôler : Position pour le TrackBar et Left pour le cercle bleu (Shape2).

III-3-1 - Lien rapide

Pourtant, impossible de faire une liaison rapide !* Frustrant, n'est-ce pas ? Quelle peut bien en être la cause ?

Pas de bol, je vous avais parlé en Introduction d'observabilité et TTrackBar est justement un de ces composants qui n'a aucune propriété observable. Malgré cela, nous avons pu ajouter la propriété dans le concepteur visuel : c'est vrai qu'il y a de quoi voir rouge !

Un tour dans la documentation sera le bienvenu pour essayer de comprendre. Quoique pas facile à trouver, on y découvre l'explication et la méthode pour remédier à ce problème.

Tutoriel : Création de composants activés LiveBindings

Hélas, toutes les propriétés d'un contrôle ne sont pas forcément, par défaut, utilisables telles quelles avec LiveBindings (surtout s'il s'agit d'un composant VCL présent depuis longtemps).

Pour qu'il soit possible d'utiliser la propriété d'un composant de façon totalement réactive, la propriété doit avoir été rendue « observable » et le composant « réactif », c'est-à-dire que :

- la propriété voulue a été déclarée comme ObservableMember ;

- des fonctions et procédures idoines sont implémentées : CanObserve, ObserverAdded.

Mais, heureusement, cela ne veut pas dire que l'on ne peut pas utiliser une propriété non déclarée « observable » dans une expression. C'est juste que l'automatisme de liaison n'est pas effectif pour ces propriétés non déclarées.

L'objectif de cet épisode n'étant pas de créer un nouveau composant observable, chose qui pourrait faire l'objet d'un autre épisode, je vous laisse aux prises avec le tutoriel cité.

À ce stade, vous pensez que : « S'il faut réécrire les composants, autant ne pas utiliser les LiveBindings , je laisse ça à FMX ! » Toutefois l'approche manuelle, décrite au chapitre III.2.5, peut être la solution, bien que cela soit un peu contraire à l'objectif de départ : « zéro code ».

III-3-2 - Lien manuel

Nous allons donc faire la même chose que dans le chapitre III.2.5.

Première étape, indispensable, il faut poser sur la forme un TBindingsList (en FMX, la création du lien rapide l'avait généré automatiquement). On profitera de l'éditeur de liaison * pour ôter les deux propriétés que nous avions mises au chapitre précédent, car elles sont devenues inutiles.

Deuxième étape, il faut ajouter une expression (BindExpression) et remplir les différentes propriétés.

Troisième étape, il s'agit de notifier, par programme, au moteur qu'il doit prendre en compte la modification de valeur, avec la même instruction que dans le chapitre déjà cité.

Voici, synthétiquement, la nouvelle présentation* dans l'EDI.

Modifications au programme VCL*

(cliquez ici pour aggrandir l'image)

Le source modifié

Au passage, notez l'ajout de plusieurs unités, dont les RTTI. Retour à la note de bas de page .

Nouveau VCL

unit U_Prog1;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.ComCtrls,
Data.Bind.EngExt, Vcl.Bind.DBEngExt, System.Rtti, System.Bindings.Outputs,
Vcl.Bind.Editors, Data.Bind.Components;

type
TForm8 = class(TForm)
TrackBar1: TTrackBar;
Shape1: TShape;
Shape2: TShape;
BindingsList1: TBindingsList;
BindExpression1: TBindExpression;
procedure TrackBar1Change(Sender: TObject);
procedure Edit1KeyPress(Sender: TObject; var Key: Char);
private
{ Déclarations privées }
public
{ Déclarations publiques }
end;

var
Form8: TForm8;

implementation

{$R *.dfm}

procedure TForm8.Edit1KeyPress(Sender: TObject; var Key: Char);
begin

end;

procedure TForm8.TrackBar1Change(Sender: TObject);
var percent : Double;
posCurseur: integer;
begin
// Méthode "Classique", Calcul décomposé pour les besoins de l'explication
// calcul du pourcentage sur la barre
Percent:=TrackBar1.Position / TrackBar1.Max;
// Calcul en pixels, Arrondi nécessaire
PosCurseur:=Round(TrackBar1.Width*Percent);
// Positionnement exact du cercle rouge
Shape1.Left:=TrackBar1.Left+posCurseur-(Shape1.Width div 2);

// Méthode via les LiveBindings
// notification d'un changement au "moteur" pour déplacer le cercle bleu
BindingsList1.Notify(Sender,'');
end;

end.

Et voici son DFM associé :

DFM associé

object Form8: TForm8
Left = 0
Top = 0
Caption = 'D'#233'placer la balle'
ClientHeight = 193
ClientWidth = 447
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object Shape1: TShape
Left = 0
Top = 80
Width = 40
Height = 41
Brush.Color = clRed
Pen.Color = clRed
Shape = stCircle
end
object Shape2: TShape
Left = 0
Top = 8
Width = 40
Height = 41
Brush.Color = clBlue
Pen.Color = clBlue
Shape = stCircle
end
object TrackBar1: TTrackBar
AlignWithMargins = True
Left = 20
Top = 145
Width = 407
Height = 45
Margins.Left = 20
Margins.Right = 20
Align = alBottom
TabOrder = 0
OnChange = TrackBar1Change
end
object BindingsList1: TBindingsList
Methods = <>
OutputConverters = <>
Left = 72
Top = 16
object BindExpression1: TBindExpression
Category = 'Expressions de liaison'
ControlComponent = Shape2
SourceComponent = TrackBar1
SourceExpression = 'Left+ Position * Width / Max - Owner.Shape2.Width/2'
ControlExpression = 'Left'
NotifyOutputs = False
Direction = dirSourceToControl
end
end
end

L'exécution du programme est conforme à l'attente.

IV - Conclusion de cet épisode

Oui, je le concède volontiers, ce n'est pas forcément concluant :

- on ne comprend pas trop à quoi cela pourrait bien servir en VCL, surtout que les composants ne sont pas tous observables (il n'y a d'ailleurs, à ma connaissance, pas de liste de ceux qui le sont) ;

- en FMX, il faut se faire une raison, les LiveBindings semblent incontournables (surtout s'il s'agit d'utilisation de sources de données), mais il y a des moments de frustration (c'est le moins que l'on puisse écrire).

Pour contrebalancer cela, cette introduction n'a pas abordé les liaisons avec des objets plus complexes ou des bases de données. De nombreux tutoriels ou vidéos existent déjà qui sont certainement plus alléchants (au niveau des possibilités) que cette introduction.

Mais je compte bien écrire d'autres épisodes et aborder ces questions !

Tous mes remerciements à Gilles (gvasseur58) et Jean-Luc (Alcatîz) pour leur relecture et conseils techniques et à Claude (ClaudeLeloup) pour ses corrections orthographiques et grammaticales.

V - Notes

Les programmes proposés ont été écrits avec la dernière version en date de publication, c'est-à-dire la version Delphi 10.2 Tokyo, pour être précis avec la version Entreprise. Néanmoins, ils sont réalisables avec la version Starter du produit, voire des versions plus anciennes.

Retour à l'article

Retour à l'article

Retour à l'article

Retour à l'article

Retour à l'article

Retour à l'article

Retour à l'article

Retour à l'article

Retour à l'article

Retour à l'article

Retour à l'article

Retour à l'article

Retour à l'article

Retour à l'article

(1)De fait une notion de liaison avec des propriétés avec des composants existait déjà, fonctionnalité peu utilisée, introduite avec D2010 et assez difficile à mettre en code : les RTTI.

(2)Malheureusement pour les détenteurs d'une version Starter, le concepteur visuel de liens n'est pas disponible. Pour eux, seule la méthode manuelle sera accessible !

(3)Détenteurs de la version Starter, il faudra d'abord ajouter un TBindingsList à votre forme.