在表单中实时绑定现存的用户对象
livebinding an extant user object in a form
我正在尝试在 VCL 窗体上使用实时绑定,其中要绑定到窗体控件的对象作为 属性 传递给窗体。我正在使用 10.1 柏林。对象中传递的属性是普通的:
Public
Property ProjectObject: TProject Read fProjectObject Write fProjectObject;
我已经使用 DataGeneratiorAdapter 和 AdapterBindSource 来使用设计器在表单上设置链接。
我不理解的地方是 OnCreateAdapter 方法中的 AdapterBindSource。我能找到的所有示例都显示了如何创建一个由控件填充的新对象,但我找不到在运行时绑定 fProjectObject(传递的对象)的方法。
我当前在 OnCreateAdapter 方法中的代码是:
ABindSourceAdapter := TObjectBindSourceAdapter<TProject>.Create(Self);
编译器可以接受,但不允许控件显示和更新 fProjectObject 中的属性。
显示此表单(项目编辑表单)的代码部分如下所示:
ProjEdit.ProjectObject := Proj;
ProjEdit.ShowModal;
StoreProject(Proj);
其中ProjEdit是项目编辑表单,ProjectObject是传递项目对象的属性,Proj是要编辑的项目对象。项目对象简单地传递给这个表单,并在对信息进行任何更改后存储。此对象在传递给此表单进行编辑之前存储在数据库中。
如何将实时绑定连接到传递的对象?
在此先感谢您的帮助
我认为可能让您感到困惑的是您的 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 对象变量实际上是一个指针,因此它可以自由地 "pointed at" 对象的现有实例。
重要的是把TObjectBindSourceAdapter
的最后一个参数设置为False,这样adapter就不会拥有Person对象,否则它(adapter)销毁的时候也会销毁Person对象。
顺便说一句,此视频中解释了重写表单构造函数的必要性:
https://delphiaball.co.uk/2015/10/19/livebindings-in-vcl-part-2-livebinding-objects/
他解释说,如果您没有在 CreateAdapter 事件之前创建要绑定的对象,绑定将清除该对象在绑定字段中已有的任何内容。
这是我的建议:
首先:在 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。
我还没有测试过这段代码 - 但我认为这应该可行...
我正在尝试在 VCL 窗体上使用实时绑定,其中要绑定到窗体控件的对象作为 属性 传递给窗体。我正在使用 10.1 柏林。对象中传递的属性是普通的:
Public
Property ProjectObject: TProject Read fProjectObject Write fProjectObject;
我已经使用 DataGeneratiorAdapter 和 AdapterBindSource 来使用设计器在表单上设置链接。
我不理解的地方是 OnCreateAdapter 方法中的 AdapterBindSource。我能找到的所有示例都显示了如何创建一个由控件填充的新对象,但我找不到在运行时绑定 fProjectObject(传递的对象)的方法。
我当前在 OnCreateAdapter 方法中的代码是:
ABindSourceAdapter := TObjectBindSourceAdapter<TProject>.Create(Self);
编译器可以接受,但不允许控件显示和更新 fProjectObject 中的属性。
显示此表单(项目编辑表单)的代码部分如下所示:
ProjEdit.ProjectObject := Proj;
ProjEdit.ShowModal;
StoreProject(Proj);
其中ProjEdit是项目编辑表单,ProjectObject是传递项目对象的属性,Proj是要编辑的项目对象。项目对象简单地传递给这个表单,并在对信息进行任何更改后存储。此对象在传递给此表单进行编辑之前存储在数据库中。
如何将实时绑定连接到传递的对象?
在此先感谢您的帮助
我认为可能让您感到困惑的是您的 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 对象变量实际上是一个指针,因此它可以自由地 "pointed at" 对象的现有实例。
重要的是把TObjectBindSourceAdapter
的最后一个参数设置为False,这样adapter就不会拥有Person对象,否则它(adapter)销毁的时候也会销毁Person对象。
顺便说一句,此视频中解释了重写表单构造函数的必要性:
https://delphiaball.co.uk/2015/10/19/livebindings-in-vcl-part-2-livebinding-objects/
他解释说,如果您没有在 CreateAdapter 事件之前创建要绑定的对象,绑定将清除该对象在绑定字段中已有的任何内容。
这是我的建议:
首先:在 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。
我还没有测试过这段代码 - 但我认为这应该可行...