Need bidirectional LiveBindings between a control and an object

前端 未结 1 1047
生来不讨喜
生来不讨喜 2021-01-31 19:45

In Delphi XE2 LiveBindings, I need to bind a VCL control of any type to a property of any type on an arbitrary (non-component) object. I can do this unidirectionally. But I ne

1条回答
  •  失恋的感觉
    2021-01-31 20:18

    I've got this working now. I did it all in the designer, but have converted it to mostly code to share it better on SO.

    Create a VCL forms project. On the form, drop each of these on the form:

    TBindScope TBindingsList TButton TButton TEdit

    Rename one of the buttons to btnLoad and the other to btnSave.

    Paste this code over your form unit (assuming it is named Form1). Assign the click handlers for the buttons and run it. Click btnLoad to populate the edit box with TPerson object data, edit the text in the edit box to a new value then click btnSave to write it back to the TPerson object.

    unit Form1;
    
    interface
    
    uses
      Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
      Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, System.Rtti,
    
      // LiveBinding units
      System.Bindings.Helper,     // Contains TBindings class
      Data.Bind.EngExt,
      Vcl.Bind.DBEngExt,
      Data.Bind.Components,
      System.Bindings.Outputs;
    
    type
      TPerson = class(TObject)
      protected
        fName: string;
        fAge: integer;
        procedure SetName(const Value: string);
      public
        property Name: string read fName write SetName;
        property Age: integer read fAge write fAge;
      end;
    
    type
      TForm1 = class(TForm)
        btnLoad: TButton;
        btnSave: TButton;
        BindScope1: TBindScope;
        BindingsList1: TBindingsList;
        Edit1: TEdit;
        procedure btnLoadClick(Sender: TObject);
        procedure btnSaveClick(Sender: TObject);
      private
        fInitialized: boolean;
        fPerson: TPerson;
        procedure Initialize;
      public
        procedure AfterConstruction; override;
        procedure BeforeDestruction; override;
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.dfm}
    
    procedure TForm1.AfterConstruction;
    begin
      inherited;
      Initialize;
    end;
    
    procedure TForm1.BeforeDestruction;
    begin
      fPerson.Free;
      inherited;
    end;
    
    procedure TForm1.btnLoadClick(Sender: TObject);
    begin
      fPerson.Name := 'Doogie Howser';
      fPerson.Age := 15;
      BindScope1.DataObject := fPerson;
    end;
    
    procedure TForm1.btnSaveClick(Sender: TObject);
    begin
      TBindings.Notify(Edit1, '');
    
      // Could also do this:
      //BindingsList1.Notify(Edit1, '');
    end;
    
    procedure TForm1.Initialize;
    var
      expression: TBindExpression;
    begin
      // Create a binding expression.
      expression := TBindExpression.Create(self);
      expression.ControlComponent := Edit1;
      expression.ControlExpression := 'Text';   // The Text property of Edit1 ...
      expression.SourceComponent := BindScope1;
      expression.SourceExpression := 'Name';    // ... is bound to the Name property of fPerson
      expression.Direction := TExpressionDirection.dirBidirectional;
    
      // Add the expression to the bindings list.
      expression.BindingsList := BindingsList1;
    
      // Create a Person object.
      fPerson := TPerson.Create;
    end;
    
    { TPerson }
    
    procedure TPerson.SetName(const Value: string);
    begin
      fName := Value;
      ShowMessage('Name changed to "'+ Value +'"');
    end;
    
    end.
    

    0 讨论(0)
提交回复
热议问题