2011-09-20 27 views
18

Trong Delphi XE2 LiveBindings, tôi cần ràng buộc điều khiển VCL thuộc bất kỳ loại nào với thuộc tính của bất kỳ loại nào trên một đối tượng tùy ý (không phải thành phần). Tôi có thể làm điều này một cách một chiều. Nhưng tôi cần phải làm điều đó theo chiều hai chiều.Cần LiveBirectings hai chiều giữa điều khiển và đối tượng

Giả sử tôi muốn ràng buộc một TPerson.PersonName: string thành TEdit.Text.

Điều tôi hiện nay thật đơn giản.

  • Tạo ứng dụng VCL mới, thêm TBindScope, TBindingsList, TEdit.
  • Tạo một phiên bản của TPerson có tên person1.
  • Sử dụng danh sách BindingList, thêm thuộc tính TBindExpression.
  • Với BindExpression
    • bộ ControlComponent để Edit1
    • bộ ControlExpression để 'Text'
    • bộ SourceComponent để BindScope1
    • bộ SourceExpression để PERSONNAME
  • Thêm một nút; cho sự kiện Nhấp tôi thêm: BindScope1.DataObject: = person1;
  • Thêm nút; cho sự kiện Nhấp tôi thêm (chỉ một sự kiện là cần thiết, nhưng cho đến khi nó hoạt động, tôi sẽ thử cả hai).
    • TBindings.Notify (sender, '');
    • BindingsList1.Notify (sender, '');

Nút đầu tiên liên kết theo hướng đầu tiên. Nút thứ hai không bao giờ có vẻ như viết lại giá trị cho thuộc tính person1.PersonName.

Tôi đã thử nghiệm với mã thông báo, hướng ràng buộc, loại ràng buộc, biểu thức, SourceMember, vv Đôi khi tôi gặp lỗi thời gian chạy trong cấu hình bindexpression, phần còn lại của thời gian ràng buộc đơn giản là một chiều.

Tôi mong đợi nhấp vào nút thứ hai và xem nội dung của Edit1.Text write to person1.PersonName.

Nếu tôi phải làm điều này tất cả từ mã, tôi sẽ xem xét nó và các ví dụ như vậy được chào đón, nhưng tôi thực sự muốn làm điều đó thông qua các nhà thiết kế nếu có thể.

Lưu ý rằng tôi không quan tâm đến việc ràng buộc giữa hai điều khiển.

Lưu ý rằng tôi đã tải xuống và kiểm tra dự án mẫu LiveBinding và không tìm thấy bất kỳ dự án nào thực hiện việc này. Nếu điều này là sai, hãy cụ thể khi chỉ ra. Tôi cũng đã đọc DocWiki. Nó không bao gồm ràng buộc hai chiều ngoại trừ việc sử dụng các điều khiển liên kết LiveBinding DB. Tôi không sử dụng các điều khiển LiveBinding của DB và tôi cũng không sử dụng Số liệu. Vì vậy, trừ khi bạn có thể giải thích cho tôi lý do tại sao tôi nên sử dụng chúng, tôi sẽ không cần bất kỳ thông tin nào về các điều khiển đó.

+0

Sử dụng DSharp thay vì LiveBindings và làm cho này một lót hai (một cho việc thực hiện các setter của một tài sản đó phải được ràng buộc ý thức và một cho việc tạo ra các ràng buộc) –

Trả lời

16

Tôi đã làm việc này ngay bây giờ. Tôi đã làm tất cả trong nhà thiết kế, nhưng đã chuyển đổi nó thành mã chủ yếu để chia sẻ nó tốt hơn trên SO.

Tạo dự án biểu mẫu VCL. Về hình thức, thả mỗi trong số này trên biểu mẫu:

TBindScope TBindingsList TButton TButton TEdit

Đổi tên một trong các nút để btnLoad và người kia để btnSave.

Dán mã này qua đơn vị biểu mẫu của bạn (giả sử nó được đặt tên là Form1). Gán các trình xử lý nhấn cho các nút và chạy nó. Nhấp vào btnLoad để điền vào hộp chỉnh sửa với dữ liệu đối tượng TPerson, chỉnh sửa văn bản trong hộp chỉnh sửa thành giá trị mới, sau đó nhấp btnSave để ghi lại đối tượng 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 không còn có sẵn như là thành phần thời gian thiết kế kể từ XE6 –

+0

Nhưng vẫn có sẵn trong thời gian chạy –

Các vấn đề liên quan