1

我正在尝试使用实时绑定来更新我的(非组件)对象的属性。我有一个 TPrototypeBindSource,用于将组件绑定到我的对象字段,并在运行时使用 TObjectBindSourceAdapter。如果调用编辑组件的 onchange 事件,我可以让它工作MyPrototypeBindSource.Refresh,但是有没有办法让它自动发生,而无需为表单上的每个组件设置 onchange 事件?

4

1 回答 1

4

虽然TPrototypeBindSource.AutoPost怀疑有一个处理将控制数据自动发布到数据对象的方法,但它并没有......仔细查看源代码,这个属性只会影响内部数据生成器。

似乎是,我们必须在创建适配器时手动设置此属性(因为我们此时也将设置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;

活绑定:

活动:ftBoolean -> CheckBox1/CheckedState(Self)
名字:ftString -> Edit1/Text
姓氏:ftString -> Edit2/Text

如果您不喜欢将该方法分配给所有控件,您可以通过调用ControlChanged来强制发布数据。但是您必须先检查它是否处于编辑模式:TPrototypeBindSourceTPrototypeBindSource.Post

if PersonSource.Editing
then
  PersonSource.Post;

每当您需要发布数据时调用它......如果在任何时候只需在TApplicationEvents.OnIdle.

于 2015-01-30T23:22:11.167 回答