2011-09-20 11 views
18

En Delphi XE2 LiveBindings, debo vincular un control VCL de cualquier tipo a una propiedad de cualquier tipo en un objeto arbitrario (no componente). Puedo hacer esto unidireccionalmente Pero necesito hacerlo bidireccionalmente.Necesita LiveBindings bidireccionales entre un control y un objeto

Digamos que quiero vincular un TPerson.PersonName: cadena a un TEdit.Text.

Lo que tengo ahora es simple.

  • Cree una nueva aplicación VCL, agregue un TBindScope, TBindingsList, TEdit.
  • Crea una instancia de TPerson llamada person1.
  • Usando una lista de vinculación, agregue una propiedad TBindExpression.
  • Con BindExpression
    • conjunto ControlComponent a Edit1
    • conjunto ControlExpression a 'Texto'
    • conjunto SourceComponent a BindScope1
    • conjunto SourceExpression a personname
  • Agregar un botón; al evento Click que agrego: BindScope1.DataObject: = person1;
  • Agregue un botón; al evento Click que agrego (solo uno es necesario, pero hasta que funcione, los probaré a ambos).
    • TBindings.Notify (remitente, '');
    • BindingsList1.Notify (remitente, '');

El primer botón se une en la primera dirección. El segundo botón nunca parece escribir el valor en la propiedad person1.PersonName.

He experimentado con el código de notificación, la dirección de enlace, tipos de enlace, expresiones, SourceMember, etc. A veces obtengo errores de tiempo de ejecución en la configuración bindexpression, el resto del tiempo el enlace es simplemente unidireccional.

Espero hacer clic en el segundo botón y ver el contenido de Edit1.Text escrito en person1.PersonName.

Si tengo que hacer todo esto desde el código, lo consideraré y tales ejemplos son bienvenidos, pero realmente quiero hacerlo a través del diseñador si es posible.

Tenga en cuenta que no estoy interesado en el enlace entre dos controles.

Tenga en cuenta también que ya he descargado e inspeccionado los proyectos de muestra LiveBinding, y no encontré ninguno que haga esto. Si esto es incorrecto, sea específico al señalarlo. También he leído el DocWiki. No cubre el enlace bidireccional excepto que usa los controles DB LiveBinding. No estoy usando los controles DB LiveBinding ni estoy usando un DataSet. Así que, a menos que pueda explicarme por qué debería usarlos, no necesitaré información sobre esos controles.

+0

Uso DSharp en lugar de LiveBindings y hacer de esto una de dos forro (uno para la implementación de la incubadora de una propiedad que debe ser vinculante conscientes y uno para la creación de la unión) –

Respuesta

16

Tengo esto funcionando ahora. Lo hice todo en el diseñador, pero lo he convertido principalmente en código para compartirlo mejor en SO.

Cree un proyecto de formularios VCL. En el formulario, la caída de cada uno de estos en la forma:

TBindScope TBindingsList TButton TButton TEdit

Cambiar el nombre de uno de los botones a btnLoad y el otro a btnSave.

Pegue este código sobre su unidad de formulario (suponiendo que se llame Form1). Asigne los manejadores de clic para los botones y ejecútelo. Haga clic en btnLoad para rellenar el cuadro de edición con los datos del objeto TPerson, edite el texto en el cuadro de edición a un nuevo valor y luego haga clic en btnGuardar para volver a escribirlo en el objeto 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 ya no está disponible como componente de tiempo de diseño desde XE6 –

+0

Pero todavía disponible en tiempo de ejecución –

Cuestiones relacionadas