在Delphi XE2 LiveBindings中,我需要将任意类型的VCL控件绑定到任意(非组件)对象上任意类型的属性。我可以单向执行此操作。但是我需要双向进行。
假设我想将TPerson.PersonName:字符串绑定到TEdit.Text。
我现在所拥有的很简单。
创建一个新的VCL应用程序,添加TBindScope,TBindingsList,TEdit。
创建一个名为person1的TPerson实例。
使用BindingList,添加TBindExpression属性。
使用BindExpression
将ControlComponent设置为Edit1
将ControlExpression设置为“文本”
将SourceComponent设置为BindScope1
将SourceExpression设置为PersonName
添加一个按钮;添加到Click事件中:BindScope1.DataObject:= person1;
添加一个按钮;添加到我添加的Click事件中(只有一个是必要的,但是在它起作用之前,我将同时尝试它们)。
TBindings.Notify(sender,'');
BindingsList1.Notify(sender,'');
第一个按钮沿第一个方向绑定。第二个按钮似乎永远不会将值写回到person1.PersonName属性。
我已经尝试过使用通知代码,绑定方向,绑定类型,表达式,SourceMember等。有时在bindexpression配置中会出现运行时错误,其余时间绑定都是单向的。
我希望单击第二个按钮,然后查看写入到person1.PersonName的Edit1.Text的内容。
如果必须通过代码来完成所有这些工作,我会考虑并欢迎此类示例,但是我真的想尽可能地通过设计器来完成。
请注意,我对两个控件之间的绑定不感兴趣。
还要注意,我已经下载并检查了LiveBinding示例项目,但没有找到任何可以执行此操作的项目。如果这是错误的,请在指出时加以具体说明。我还阅读了DocWiki。除使用DB LiveBinding控件外,它不涵盖双向绑定。我没有使用DB LiveBinding控件,也没有使用DataSet。因此,除非您能向我解释为什么我应该使用它们,否则我将不需要有关这些控件的任何信息。
最佳答案
我现在已经开始工作了。我在设计器中完成了所有工作,但已将其转换为大部分代码,以便在SO上更好地共享。
创建一个VCL表单项目。在表单上,将其中的每一个拖放到表单上:
TBindScope
TBindingsList
T按钮
T按钮
编辑
将其中一个按钮重命名为btnLoad,将另一个按钮重命名为btnSave。
将此代码粘贴到您的表单单元上(假设它名为Form1)。为按钮分配点击处理程序并运行它。单击btnLoad用TPerson对象数据填充编辑框,将编辑框中的文本编辑为新值,然后单击btnSave将其写回到TPerson对象。
unit Form1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, System.Rtti,
// LiveBinding units
System.Bindings.Helper, // Contains TBindings class
Data.Bind.EngExt,
Vcl.Bind.DBEngExt,
Data.Bind.Components,
System.Bindings.Outputs;
type
TPerson = class(TObject)
protected
fName: string;
fAge: integer;
procedure SetName(const Value: string);
public
property Name: string read fName write SetName;
property Age: integer read fAge write fAge;
end;
type
TForm1 = class(TForm)
btnLoad: TButton;
btnSave: TButton;
BindScope1: TBindScope;
BindingsList1: TBindingsList;
Edit1: TEdit;
procedure btnLoadClick(Sender: TObject);
procedure btnSaveClick(Sender: TObject);
private
fInitialized: boolean;
fPerson: TPerson;
procedure Initialize;
public
procedure AfterConstruction; override;
procedure BeforeDestruction; override;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.AfterConstruction;
begin
inherited;
Initialize;
end;
procedure TForm1.BeforeDestruction;
begin
fPerson.Free;
inherited;
end;
procedure TForm1.btnLoadClick(Sender: TObject);
begin
fPerson.Name := 'Doogie Howser';
fPerson.Age := 15;
BindScope1.DataObject := fPerson;
end;
procedure TForm1.btnSaveClick(Sender: TObject);
begin
TBindings.Notify(Edit1, '');
// Could also do this:
//BindingsList1.Notify(Edit1, '');
end;
procedure TForm1.Initialize;
var
expression: TBindExpression;
begin
// Create a binding expression.
expression := TBindExpression.Create(self);
expression.ControlComponent := Edit1;
expression.ControlExpression := 'Text'; // The Text property of Edit1 ...
expression.SourceComponent := BindScope1;
expression.SourceExpression := 'Name'; // ... is bound to the Name property of fPerson
expression.Direction := TExpressionDirection.dirBidirectional;
// Add the expression to the bindings list.
expression.BindingsList := BindingsList1;
// Create a Person object.
fPerson := TPerson.Create;
end;
{ TPerson }
procedure TPerson.SetName(const Value: string);
begin
fName := Value;
ShowMessage('Name changed to "'+ Value +'"');
end;
end.