XE3 Visual LiveBindings: User defined objects

Posted by on in Blogs
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



Comments are not available for public users. Please login first to view / add comments.