I need to bi-directionaly bind Synedit to column 'text' in database. It works with memo component, but for Synedit or i.e. Richedit is created only one-directional binding. Value is synchronized from database, but i don't know how to update back to database from Synedit.
I try in the Livebinding designer simple connect fields like on picture, but it i'm stuck in documentation.
I need automatically synchronized database field when i leave editor, like it works with Memo component.
The reason that TSynMemo does not behave like TMemo is that 'out of the box' it has no support the LiveBindings observers
necessary to make LB work. The way to overcome this is to derive a TSynMemo
descendent which does support LB observers and use that instead.
Luckily, there is an Embarcadero wiki entry which explains how to add LB observers to components which lack them. Based on that, with a little preparatory settting up, the example code should do what you want:
On a new form, drop a TClientDataSet, TDataSource, TDBGrid and a TDNavigator and link them up in the usual way. Using a TClientDataSet is to allow a completely self-contained sample project. Note If you want to use FireDAC. you can equally well use a TFDMemTable instead of a TClientDataSet; the steps and code below will be identical, and I've tested that this FD alternative works.
Set up ID, Name (String(20)) and Memo fields on the TClientDataSet as shown in the code
Add a TBSynEdit connected via the TDataSource to the Memo Field. The purpose of this is to show that the live-bound TSynMemo which we'll add next performs in the same way
Add a TSynMemo, TMemo, TBindingList, TBindSourceDB, and TBindNavigator to the form
Use the quick-binding pop-up to add TLinkControlToFields to link the TSynEdit and the TMemo to the Memo field of the ClientDataSet
Connect the *
property of the BindSourceDB to the *
property of the TBindNavigator in the visual LB designer.
Now, add the code below to the Form. To save having to register our TSynMemo
descendant as a component and install it in the IDE, the code declares it
in the form unit as an Interposer class
. It implements all the obsever methods
that seem to be necessary to live-bind a TSynMemo.
Code
type
TSynMemo = class(SynMemo.TSynMemo)
private
procedure ObserverToggle(const AObserver: IObserver; const Value: Boolean);
protected
procedure DoChange; override;
function CanObserve(const ID: Integer): Boolean; override; { declaration is in System.Classes }
procedure ObserverAdded(const ID: Integer; const Observer: IObserver); override; { declaration is in System.Classes }
end;
TForm2 = class(TForm)
ClientDataSet1: TClientDataSet;
DataSource1: TDataSource;
DBGrid1: TDBGrid;
DBNavigator1: TDBNavigator;
SynMemo1: TSynMemo;
ClientDataSet1ID: TIntegerField;
ClientDataSet1Name: TStringField;
ClientDataSet1Memo: TMemoField;
BindingsList1: TBindingsList;
BindNavigator1: TBindNavigator;
Memo1: TMemo;
BindSourceDB1: TBindSourceDB;
LinkControlToField1: TLinkControlToField;
LinkControlToField2: TLinkControlToField;
DBSynEdit1: TDBSynEdit;
procedure FormCreate(Sender: TObject);
public
end;
[...]implementation[...]
function TSynMemo.CanObserve(const ID: Integer): Boolean;
{ Controls which implement observers always override TComponent.CanObserve(const ID: Integer). }
{ This method identifies the type of observers supported by TObservableTrackbar. }
begin
case ID of
TObserverMapping.EditLinkID, { EditLinkID is the observer that is used for control-to-field links }
TObserverMapping.ControlValueID:
Result := True;
else
Result := False;
end;
end;
procedure TSynMemo.DoChange;
begin
inherited;
TLinkObservers.ControlChanged(Self);
end;
procedure TSynMemo.ObserverAdded(const ID: Integer; const Observer: IObserver);
begin
if ID = TObserverMapping.EditLinkID then
Observer.OnObserverToggle := ObserverToggle;
end;
procedure TSynMemo.ObserverToggle(const AObserver: IObserver; const Value: Boolean);
var
LEditLinkObserver: IEditLinkObserver;
begin
EXIT; // do nothing
end;
const
sDfm = 'DFM';
procedure TForm2.FormCreate(Sender: TObject);
begin
ClientDataSet1.IndexFieldNames := 'ID';
ClientDataSet1.CreateDataSet;
ClientDataSet1.InsertRecord([1, 'Row1', 'Memo1']);
ClientDataSet1.InsertRecord([2, 'Row2', 'Memo two']);
end;
initialization
Data.Bind.Components.RegisterObservableMember(TArray<TClass>.Create(
TSynMemo
),
'Lines.Text', sDfm);
finalization
Data.Bind.Components.UnregisterObservableMember(TArray<TClass>.Create(TSynMemo));
end.