delphi delphi-xe2 livebindings

delphi - Necesita LiveBindings bidireccionales entre un control y un objeto



delphi-xe2 (1)

En Delphi XE2 LiveBindings, necesito 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.

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 BindingList, agregue una propiedad TBindExpression.
  • Con BindExpression
    • establecer ControlComponent a Edit1
    • establecer ControlExpression en ''Texto''
    • establecer SourceComponent a BindScope1
    • establecer SourceExpression para PersonName
  • Agregar un botón; al evento Click que agrego: BindScope1.DataObject: = person1;
  • Agregar un botón; al evento Click que agrego (solo uno es necesario, pero hasta que funcione, los probaré a ambos).
    • TBindings.Notify (emisor, '''');
    • BindingsList1.Notify (emisor, '''');

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, los tipos de enlace, las 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 la unión 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.


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

Crear un proyecto de formularios VCL. En el formulario, suelte cada uno de estos en el formulario:

TBindScope TBindingsList TButton TButton TEdit

Cambie el nombre de uno de los botones a btnLoad y el otro a btnGuardar.

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.