我正在尝试使用livebindings来更新我的(非组件)对象的属性。我有一个TPrototypeBindSource,我用它来将组件绑定到我的对象字段,并在运行时使用TObjectBindSourceAdapter。如果在编辑组件的onchange事件中调用MyPrototypeBindSource.Refresh
,我可以使它工作,但是有没有办法让它自动发生,而不为表单上的每个组件设置onchange事件?
答案 0 :(得分:4)
虽然有TPrototypeBindSource.AutoPost
我suspect来处理控制数据到数据对象的自动发布但它没有......很好地查看源,这个属性只会影响内部数据发生器。
似乎是,我们必须在创建适配器时手动设置此属性(因为我们此时也会设置AutoEdit
):
procedure TForm1.PrototypeBindSource1CreateAdapter( Sender: TObject; var ABindSourceAdapter: TBindSourceAdapter );
begin
FPerson := TPerson.Create;
ABindSourceAdapter := TObjectBindSourceAdapter<TPerson>.Create( Self, FPerson );
ABindSourceAdapter.AutoEdit := True;
ABindSourceAdapter.AutoPost := True;
end;
每次离开 TEdit
但TCheckBox
时,这都可以胜任
将立即发布数据。
要更改此设置,只需使用published
方法
procedure TForm1.ControlChanged( Sender: TObject );
begin
if Sender is TComponent
then
TLinkObservers.ControlChanged( Sender as TComponent );
end;
并将其分配给每个所需的控件(例如TEdit.OnChange
)以立即将数据提供给数据对象。
这里整体一气呵成
type
TPerson = class
private
FFirstname: string;
FLastname: string;
FActive: Boolean;
public
function ToString: string; override;
property Active: Boolean read FActive write FActive;
property Firstname: string read FFirstname write FFirstname;
property Lastname: string read FLastname write FLastname;
end;
TForm1 = class( TForm )
PersonSource: TPrototypeBindSource; { OnCreateAdapter -> PersonSourceCreateAdapter }
Edit1: TEdit; { OnChange -> ControlChanged }
Edit2: TEdit; { OnChange -> ControlChanged }
BindingsList1: TBindingsList;
LinkControlToField1: TLinkControlToField;
LinkControlToField2: TLinkControlToField;
Label1: TLabel;
ApplicationEvents1: TApplicationEvents; { OnIdle -> ApplicationEvents1Idle }
CheckBox1: TCheckBox;
LinkControlToField3: TLinkControlToField;
procedure PersonSourceCreateAdapter( Sender: TObject; var ABindSourceAdapter: TBindSourceAdapter );
procedure ApplicationEvents1Idle( Sender: TObject; var Done: Boolean );
private
FPerson: TPerson;
published
procedure ControlChanged( Sender: TObject );
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.ApplicationEvents1Idle( Sender: TObject; var Done: Boolean );
begin
// just for checking then object data
Label1.Caption := FPerson.ToString;
end;
procedure TForm1.ControlChanged( Sender: TObject );
begin
if Sender is TComponent
then
TLinkObservers.ControlChanged( Sender as TComponent );
end;
procedure TForm1.PersonSourceCreateAdapter( Sender: TObject; var ABindSourceAdapter: TBindSourceAdapter );
begin
FPerson := TPerson.Create;
ABindSourceAdapter := TObjectBindSourceAdapter<TPerson>.Create( Self, FPerson );
ABindSourceAdapter.AutoEdit := True;
ABindSourceAdapter.AutoPost := True;
end;
{ TPerson }
function TPerson.ToString: string;
begin
Result := FLastname + ', ' + FFirstname + ' ' + BoolToStr( FActive );
end;
LiveBindings:
Active : ftBoolean -> CheckBox1/CheckedState(Self) Firstname : ftString -> Edit1/Text Lastname : ftString -> Edit2/Text
如果您不想将ControlChanged
方法分配给所有控件,可以强制TPrototypeBindSource
通过调用TPrototypeBindSource.Post
发布数据。但是你必须首先检查它是否处于编辑模式:
if PersonSource.Editing
then
PersonSource.Post;
每当您需要发布数据时都要调用此信息...如果在任何时候只需在TApplicationEvents.OnIdle
内调用它。