需要控件和对象之间的双向LiveBindings [英] Need bidirectional LiveBindings between a control and an object

查看:131
本文介绍了需要控件和对象之间的双向LiveBindings的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Delphi XE2 LiveBindings中,我需要将任何类型的VCL控件绑定到任意(非组件)对象上的任何类型的属性。我可以单向地做到这一点。但是我需要双向进行。



我想要将一个TPerson.PersonName:string绑定到一个TEdit.Text。



我现在很简单




  • 创建一个新的VCL应用程序,添加一个TBindScope,TBindingsList,TEdit。

  • 创建一个实例的TPerson命名为person1。

  • 使用BindingList添加TBindExpression属性。

  • 使用BindExpression


    • 将ControlComponent设置为Edit1



    • 将ControlExpression设置为'文本'



    • 将SourceComponent设置为BindScope1



    • 将SourceExpression设置为PersonName


  • 添加一个按钮;到Click事件我添加:BindScope1.DataObject:= person1;

  • 添加一个按钮;对于点击事件,我添加(只有一个是必要的,但直到它工作,我会尝试他们两者)。


    • TBindings.Notify(发件人, '');



    • BindingsList1.Notify(sender,'');




第一个按钮在第一个方向绑定。第二个按钮从来没有似乎将该值写回person1.PersonName属性。



我已经尝试过通知代码,绑定方向,绑定类型,表达式,SourceMember等。有时我在bindexpression配置中遇到运行时错误,其余的我们希望单击第二个按钮并查看编辑给person1.PersonName的Edit1.Text的内容。





如果我必须从代​​码中完成所有这些,我会考虑它,这样的例子是受欢迎的,但是我真的想通过设计师来做到这一点。 / p>

请注意,我对两个控件之间的绑定不感兴趣。注意,我也已经下载并检查了LiveBinding示例项目,没有找到任何操作。如果这是错误的,请具体指出它。我也读过DocWiki。它不包括双向绑定,除了使用 DB LiveBinding控件。我没有使用 DB LiveBinding控件,也没有使用DataSet。所以除非你可以向我解释为什么要使用它们,否则我不需要有关这些控件的任何信息。

解决方案

我现在有这个工作。我在设计师中做了这一切,但是将其转换为大部分代码,以便在SO上更好地分享它。



创建VCL表单项目。在表单上,​​删除以下表单中的每一个:



TBindScope
TBindingsList
TButton
TButton
TEdit

将其中一个按钮重命名为btnLoad,另一个按钮转换为btnSave。



将此代码粘贴到您的表单上(假设它被命名为Form1)。分配按钮的点击处理程序并运行它。单击btnLoad以使用TPerson对象数据填充编辑框,将编辑框中的文本编辑为新值,然后单击btnSave将其写回TPerson对象。

 单位Form1; 

接口

使用
Winapi.Windows,Winapi.Messages,System.SysUtils,System.Variants,System.Classes,Vcl.Graphics,
Vcl.Controls,Vcl.Forms,Vcl.Dialogs,Vcl.StdCtrls,System.Rtti,

// LiveBinding单位
System.Bindings.Helper,//包含TBindings类
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
属性名称:string read fName write SetName;
属性年龄:整数读fAge写fAge;
结束

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;
程序初始化;
public
procedure AfterConstruction;覆盖
程序BeforeDestruction;覆盖
结束

var
Form1:TForm1;

实现

{$ R * .dfm}

程序TForm1.AfterConstruction;
开始
继承;
初始化;
结束

程序TForm1.BeforeDestruction;
begin
fPerson.Free;
继承;
结束

程序TForm1.btnLoadClick(发件人:TObject);
begin
fPerson.Name:='Doogie Howser';
fPerson.Age:= 15;
BindScope1.DataObject:= fPerson;
结束

procedure TForm1.btnSaveClick(Sender:TObject);
begin
TBindings.Notify(Edit1,'');

//也可以这样做:
//BindingsList1.Notify(Edit1,'');
结束

程序TForm1.Initialize;
var
表达式:TBindExpression;
begin
//创建绑定表达式。
expression:= TBindExpression.Create(self);
expression.ControlComponent:= Edit1;
expression.ControlExpression:='Text'; // Edit1的Text属性...
expression.SourceComponent:= BindScope1;
expression.SourceExpression:='Name'; // ...绑定到fPerson的名称属性
expression.Direction:= TExpressionDirection.dirBidirectional;

//将表达式添加到绑定列表中。
expression.BindingsList:= BindingsList1;

//创建一个Person对象。
fPerson:= TPerson.Create;
结束

{TPerson}

程序TPerson.SetName(const Value:string);
begin
fName:= Value;
ShowMessage('Name change to''+ Value +'');
结束

结束。


In Delphi XE2 LiveBindings, I need to bind a VCL control of any type to a property of any type on an arbitrary (non-component) object. I can do this unidirectionally. But I need to do it bidirectionally.

Let's say I want to bind a TPerson.PersonName: string to a TEdit.Text.

What I have now is simple.

  • Create a new VCL application, add a TBindScope, TBindingsList, TEdit.
  • Create an instance of TPerson named person1.
  • Using a BindingList, add a TBindExpression property.
  • With BindExpression
    • set ControlComponent to Edit1
    • set ControlExpression to 'Text'
    • set SourceComponent to BindScope1
    • set SourceExpression to PersonName
  • Add a button; to the Click event I add: BindScope1.DataObject := person1;
  • Add a button; to the Click event I add (only one is necessary, but until it works I will try them both).
    • TBindings.Notify(sender, '');
    • BindingsList1.Notify(sender, '');

The first button binds in the first direction. The second button never seems to write the value back to the person1.PersonName property.

I've experimented with the notification code, the binding direction, binding types, expressions, SourceMember, etc. Sometimes I get runtime errors in the bindexpression configuration, the rest of the time the binding is simply unidirectional.

I expect to click the second button and see the contents of Edit1.Text written to person1.PersonName.

If I have to do this all from code, I'll consider it and such examples are welcome, but I really want to do it through the designer if possible.

Note that I am not interested in binding between two controls.

Note too that I have already downloaded and inspected the LiveBinding sample projects, and didn't find any that do this. If this is wrong, please be specific when pointing it out. I have also read the DocWiki. It does not cover bidirectional binding except using the DB LiveBinding controls. I am not using the DB LiveBinding controls nor am I using a DataSet. So unless you can explain to me why I should use them, I won't be needing any information about those controls.

解决方案

I've got this working now. I did it all in the designer, but have converted it to mostly code to share it better on SO.

Create a VCL forms project. On the form, drop each of these on the form:

TBindScope TBindingsList TButton TButton TEdit

Rename one of the buttons to btnLoad and the other to btnSave.

Paste this code over your form unit (assuming it is named Form1). Assign the click handlers for the buttons and run it. Click btnLoad to populate the edit box with TPerson object data, edit the text in the edit box to a new value then click btnSave to write it back to the TPerson object.

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.

这篇关于需要控件和对象之间的双向LiveBindings的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆