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

Pourquoi utiliser les LiveBindings ?

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

2 commentaires Donner une note à l'article (5)

Article lu   fois.

L'auteur

Profil Pro

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

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 »

Image non disponible
Design de la forme

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

Unité VCL
Sélectionnez
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
Sélectionnez
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 .
Image non disponible

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.

Image non disponible
Liste des membres liables *

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

Image non disponible
Conception visuelle *

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.

Image non disponible
Propriétés du lien

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
Sélectionnez
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
Sélectionnez
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
Sélectionnez
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),

Image non disponible

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.

Image non disponible
Liaison rapide

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.

Image non disponible

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.

Image non disponible
Types de lien

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.

Image non disponible

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 !

Image non disponible

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.

Image non disponible
Niveau visuel*

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
Sélectionnez
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
Sélectionnez
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 ?

Image non disponible
VCL Liaison rapide*

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 LiveBindingsTutoriel : 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.

Image non disponible
Modifications au programme VCL*

Le source modifié

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

Nouveau VCL
Sélectionnez
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é
Sélectionnez
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.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   


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.
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 !
Détenteurs de la version Starter, il faudra d'abord ajouter un TBindingsList à votre forme.

  

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.