我试图在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连接到传递的对象?
提前感谢您的帮助
答案 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。
我还没有测试过这段代码 - 但我认为这应该有用......