2011-09-20 40 views
18

在Delphi XE2 LiveBindings中,我需要將任何類型的VCL控件綁定到任意(非組件)對象上的任何類型的屬性。我可以單向做到這一點。但我需要雙向執行。需要控件和對象之間的雙向LiveBindings

比方說,我想要將一個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(發件人, '');

的第一個按鈕結合在第一方向上。第二個按鈕似乎永遠不會將值寫回到person1.PersonName屬性。

我已經試驗過通知代碼,綁定方向,綁定類型,表達式,SourceMember等等。有時我會在bindexpression配置中獲得運行時錯誤,其餘時間綁定只是單向的。

我期望點擊第二個按鈕,看到寫入person1.PersonName的Edit1.Text的內容。

如果我必須從代​​碼中完成這一切,我會考慮它,並歡迎這樣的例子,但如果可能的話,我真的想通過設計器來完成。

請注意,我對兩個控件之間的綁定不感興趣。

還要注意,我已經下載並檢查了LiveBinding示例項目,並沒有發現任何這樣做。如果這是錯誤的,請在指出時詳細說明。我也讀過DocWiki。它不包括除使用LiveBinding控件的DB控件外的雙向綁定。我沒有使用DB LiveBinding控件,也不使用DataSet。所以除非你能向我解釋爲什麼我應該使用它們,否則我不需要任何關於這些控件的信息。

+0

使用DSharp代替LiveBindings,這使兩個班輪因爲XE6 –

回答

16

我現在有這個工作。我在設計師中完成了所有工作,但已將其轉換爲主要代碼,以便在SO上更好地分享它。

創建一個VCL表單項目。上的形式,滴每個這些表單上:

TBindScope TBindingsList TButton的 TButton的 TEDIT

重命名按鈕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. 
+0

TBindScope不再作爲設計時組件但在運行時仍然可用 –

+0

(一個用於實現setter方法應該結合意識到,一個用於創建綁定) –

相關問題