Skip to content

XE3 Visual LiveBindings: User defined objects

The adapter components TListBindSourceAdapter and TObjectBindSourceAdapter enable LiveBindings with user defined TObjects.

Here is a user defined TObject  for example.

type
  TContact = class
  private
    FFirstName: string;
    FLastName: string;
  public
    constructor Create; overload;
    constructor Create(const AFirstName, ALastName: string); overload;
    property FirstName: string read FFirstName write FFirstName;
    property LastName: string read FLastName write FLastName;
  end;

  function LoadContacts: TList<TContact>;
implementation

function LoadContacts: TList<TContact>;
begin
  Result := TObjectList<TContact>.Create;
  // TODO: Load data from file
  Result.Add(TContact.Create('Adam', 'Barns'));
  Result.Add(TContact.Create('Chris', 'Decker'));
  Result.Add(TContact.Create('Emma', 'Fisk'));
end;

One way to use TListBindSourceAdapter is to instantiate the adapter at run time.  Drop a TAdapterBindSourceAdapter on the form and implement the CreateAdapter event as follows:

mplementation

{$R *.dfm}

uses ContactsUnit, System.Generics.Collections;

procedure TForm1.AdapterBindSource1CreateAdapter(Sender: TObject;
  var ABindSourceAdapter: TBindSourceAdapter);
begin
  ABindSourceAdapter := TListBindSourceAdapter<TContact>.Create(Self,
    LoadContacts);
end;i

In the LiveBindings designer, we won’t see the fields for TContact because the TContact type is not known at design time.

Drop a TStringGrid on the form and connection the ‘*’ of AdapterBindSource1 to StringGrid1.

A navigator can be added by right clicking AdapterBindSource1 and choosing "Add Navigator".

The grid is populated when the application is run:

A TDataGeneratorAdapter can be used to provide some fields to use at design time.  Add fields with the same name as the properties in TContact.  Set AdapterBindSource1.Adapter to DataGeneratorAdapter1.

The form shows sample data and the LiveBindings designer shows field names.

To show this data at design time, the TDataGeneratorAdapter fields have FieldType: ftString and Generator: LoremIpsum.

The LiveBindings designer can be used to connect fields to controls.

Note that an easy way to create a TLabeledEdit is to right click on FirstName then choose "Link to new control…".

At runtime, the TListBindSourceAdapter will be used instead of DataGeneratorAdapter1 because of the CreateAdapter event.

Another way to use TListBindSourceAdapter is to register a custom component.  Instead of instantiating a TListBindSourceAdapter in the CreateAdapter event, the custom component is dropped from the tool palette.  A TDataGeneratorAdapter is not needed.

The minimal code to for a custom adapter looks like this:

unit ContactsAdapter;

interface

  uses ContactsUnit, Data.Bind.ObjectScope, System.Classes, System.Generics.Collections;

type

  TContactsAdapter = class(TListBindSourceAdapter<TContact>)
  public
    constructor Create(AOwner: TComponent); override;
  end;

implementation

{ TContactsAdapter }

constructor TContactsAdapter.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  SetList(LoadContacts);
end;

To register the custom adapter, you will need to create and register a package which contains the custom adapter component and TContact class.  You will also need and a Register method to register the custom component.

unit ContactsAdapterReg;

interface

procedure Register;

implementation

uses System.Classes, ContactsAdapter, ContactsAdapter2;

procedure Register;
begin
  RegisterComponents('Test', [TContactsAdapter]);
end;

end.

A complete implementation of a custom adapter publishes properties and methods:

  TContactsAdapter2 = class(TListBindSourceAdapter<TContact>)
  public
    constructor Create(AOwner: TComponent); override;
  published
    property OnBeforeSetList;
    property OnAfterSetList;
    property OnListAppend;
    property OnListDelete;
    property OnListInsert;
    property OnCreateItemInstance;
    property OnInitItemInstance;
    property Options;
    property AutoEdit;
    property BeforeOpen;
    property AfterOpen;
    property BeforeClose;
    property AfterClose;
    property BeforeInsert;
    property AfterInsert;
    property BeforeEdit;
    property AfterEdit;
    property BeforePost;
    property AfterPost;
    property BeforeCancel;
    property AfterCancel;
    property BeforeDelete;
    property AfterDelete;
    property BeforeScroll;
    property AfterScroll;
    property BeforeRefresh;
    property AfterRefresh;
    property BeforeApplyUpdates;
    property AfterApplyUpdates;
    property BeforeCancelUpdates;
    property AfterCancelUpdates;
    property OnDeleteError;
    property OnInsertError;
    property OnEditError;
    property OnPostError;
    property OnApplyUpdatesError;
    property OnCancelUpdatesError;
    property OnApplyUpdates;
    property OnCancelUpdates;
    property OnHasUpdates;
  end;

TObjectBindSourceAdapter is used instead of TListBindSourceAdapter to bind to a single object, rather than a list of objects.

TObjectBindSourceAdapter is instantiated like this:

procedure TForm1.AdapterBindSource1CreateAdapter(Sender: TObject;
  var ABindSourceAdapter: TBindSourceAdapter);
begin
  ABindSourceAdapter := TObjectBindSourceAdapter<TContact>.Create(Self,
    TContact.Create('Adam', 'Barns'));
end;

At run time, there is only a single row of data.

Source forge samples

https://radstudiodemos.svn.sourceforge.net/svnroot/radstudiodemos/branches/RadStudio_XE3/LiveBindings/observers

  • ContactsAdapterPackage.dpk
    • Implements a custom TListBindSourceAdapter component
  • ListAdapterEventProject.dpr
    • Demonstrates  TAdapterBindSource.CreateAdapter event
  • ListAdapterComponentProject.dpr
    • Demonstrates custom TListBindSourceAdapter component
  • Project: CppListAdapterEventProject.dpr
    • Cpp project demonstrates  TAdapterBindSource.CreateAdapter event

{ 2 } Comments

  1. Daniel | December 17, 2012 at 12:05 pm | Permalink

    How i work with composite objects like

    TPerson = class
    property Name: string;
    end;

    Tcontract = class
    property Owner: TPerson;
    end;

    Have any example?

  2. Felipe Mesturini | June 26, 2013 at 9:11 am | Permalink

    Hi,
    Can I make this exemple with a Color property in the grid?
    If it possible.
    ok

    Sorry by my bad english.

Post a Comment

Your email is never published nor shared. Required fields are marked *

Bad Behavior has blocked 26 access attempts in the last 7 days.

Close