时间:2017-03-05 08:09:34

标签: delphi livebindings

我试图在VCL表单上使用livebindings,其中绑定到表单上的控件的对象作为属性传递给表单。我正在使用10.1柏林。对象传递的属性是普通的:

 Public
      Property ProjectObject: TProject Read fProjectObject Write fProjectObject;

我使用DataGeneratiorAdapter和AdapterBindSource使用设计器在表单上设置链接。

我对OnCreateAdapter方法中的AdapterBindSource缺乏了解。我可以找到的所有示例都显示如何创建一个由控件填充的新对象,但是我找不到在runtinme fProjectObject(传递的对象)上绑定的方法。

我在OnCreateAdapter方法中的当前代码是:

ABindSourceAdapter := TObjectBindSourceAdapter<TProject>.Create(Self);

编译器可以接受,但不允许控件显示和更新fProjectObject中的属性。

显示此表单的代码部分之一(项目编辑表单)如下所示:

ProjEdit.ProjectObject := Proj;
ProjEdit.ShowModal;
StoreProject(Proj);

在ProjEdit是项目编辑表单的地方,ProjectObject是传递项目对象的属性,Proj是要编辑的项目对象。只需将项目对象传递给此表单,并在对信息进行任何更改后进行存储。在传递给此表单进行编辑之前,此对象存储在数据库中。

如何将livebindings连接到传递的对象?

提前感谢您的帮助

2 个答案:

答案 0 :(得分:1)

我认为可能让你绊倒的事情是ProjectObject需要的非常明显的一点 要在CreateAdapter事件触发 之前创建。为了确保这一点 发生这种情况时,您需要覆盖表单的Create方法并在那里创建ProjectObject。

以下对我来说很好:

type

  TPerson = class
  private
    FLastName: String;
    FFirstName: String;
  public
    property FirstName : String read FFirstName write FFirstName;
    property LastName : String read FLastName write FLastName;
  end;

  TForm1 = class(TForm)
    edFieldA: TEdit;
    edFieldB: TEdit;
    BindNavigator1: TBindNavigator;
    PrototypeBindSource1: TPrototypeBindSource;
    BindingsList1: TBindingsList;
    LinkControlToField1: TLinkControlToField;
    LinkControlToField2: TLinkControlToField;
    procedure PrototypeBindSource1CreateAdapter(Sender: TObject; var
        ABindSourceAdapter: TBindSourceAdapter);
  private
  public
    Person : TPerson;
    constructor Create(AOwner : TComponent);  override;
  end;

[...]

constructor TForm1.Create(AOwner: TComponent);
begin
  Person := TPerson.Create;
  Person.FirstName := 'John';
  Person.LastName := 'Smith';
  inherited;
end;

procedure TForm1.PrototypeBindSource1CreateAdapter(Sender: TObject; var
    ABindSourceAdapter: TBindSourceAdapter);
begin
  ABindSourceAdapter := TObjectBindSourceAdapter<TPerson>.Create(Self, Person, False);
end;

更新不必在表单上创建表单上的Person对象。它可以简单地分配给以前存在的对象,如

constructor TForm1.Create(AOwner: TComponent);
begin
  Person := SomeTPersonObjectCreatedAlreadyInOtherCode;
  inherited;
end;

如果要在我的示例中验证,请在单元的初始化部分中创建TPerson实例,并在表单的Create构造函数中将Form1.Person指定给它。你可能没有意识到的事情是Delphi对象变量实际上是一个指针,因此它可以自由地“指向”现有的对象实例。

重要的是将TObjectBindSourceAdapter的最终参数设置为False,以便适配器不拥有Person对象,否则当它(适配器)被销毁时它将销毁Person对象。

顺便说一下,在本视频中解释了覆盖表单构造函数的需求:

https://delphiaball.co.uk/2015/10/19/livebindings-in-vcl-part-2-livebinding-objects/

他解释说,如果在CreateAdapter事件之前没有创建要绑定的对象,绑定将清除对象在绑定字段中已有的任何内容。

答案 1 :(得分:1)

以下是我的建议:

首先:在AdapterBindSource的CreateAdapter中使用以下内容:

procedure TfrmProjectEdit.AdapterBindSource1CreateAdapter(Sender: TObject; var ABindSourceAdapter: TBindSourceAdapter);
begin
  fProjectObject:=TProject.Create;
  ABindSourceAdapter:=TObjectBindSourceAdapter<TProject>.Create(self, fProjectObject, True);
end;

第二:为项目属性使用setter,例如:

procedure TfrmProjectEdit.SetProject (aProject: TProject);
begin
  fProjectObject:=aProject;
  AdapterBindSource1.Refresh;
end;

快速解释:AdapterBindSource将拥有fProjectObject并在释放ABS时释放它。我们只需为fProjectObject分配一个新值,并在setter中刷新ABS。

我还没有测试过这段代码 - 但我认为这应该有用......