我正在尝试使用实时绑定来更新我的(非组件)对象的属性。我有一个TPrototypeBindSource,用于将组件绑定到我的对象字段,并在运行时使用TObjectBindSourceAdapter。如果在编辑组件的onchange事件中调用MyPrototypeBindSource.Refresh
可以使它正常工作,但是有没有一种方法可以自动进行此操作,而无需为表单上的每个组件设置onchange事件?
最佳答案
尽管有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
If you do not like to assign the ControlChanged
method to all controls you can force the TPrototypeBindSource
to post the data by calling TPrototypeBindSource.Post
. But you have to check first if it is in edit mode:
if PersonSource.Editing
then
PersonSource.Post;
每当您需要发布数据时都可以调用此方法……如果随时可以在
TApplicationEvents.OnIdle
中调用它。