Ver Mensaje Individual
  #10  
Antiguo 27-09-2016
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Reputación: 30
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Hola Iván.

Si tuviera que volver al área de las interfaces de usuario, probablemente yo diseñaría esa pantalla de otra manera. Sin embargo, recordando algo acerca de los data links, decidí escribir una pequeña prueba que puede servirte.

Todos los controles data-aware poseen en su interior un objeto que sirve como enlace entre el control (en este caso un DBEdit) y el componente DataSource asociado. Dicho objeto es el DataLink —enlace de datos— del control. Usando el depurador, poniendo sencillos puntos de ruptura en algunos eventos, puedes darte cuenta de que cuando un componente DBEdit pierde el foco, éste llama a un método de nombre UpdateRecord de su objeto interno DataLink.
Código Delphi [-]
procedure TDBEdit.CMExit(var Message: TCMExit);
begin
  try
    FDataLink.UpdateRecord;
  //...
Dentro de la llamada a UpdateRecord se realiza la validación del texto capturado en el DBEdit y la asignación de ese texto al respectivo campo TField (que existe aunque no sea persistente). Parece entonces que llamar al método UpdateRecord del enlace de datos desde tu manejador de eventos OnKeyPress podría ser más que útil. Pero desafortunadamente estos enlaces de datos están declarados de forma privada en la mayoría de los controles data-aware. No obstante, es posible acceder a ellos mediante la lista DataLinks del objeto DataSource asociado. Esta lista contiene los enlaces de datos de todos los controles de captura que emplean el objeto DataSource en cuestión para leer o escribir el contenido de uno o más campos.
Código Delphi [-]
  TDataSource = class(TComponent)
  private
    //...
    FDataLinks: TList<TDataLink>;
    //...
  protected
    property DataLinks: TList<TDataLink> read FDataLinks;
  //...
Al ser TDataSource.DataLinks una propiedad protegida, y no privada, podemos acceder a ella de forma segura mediante el clásico truco de definir una hipotética clase hija TDataSourceAccess, o de forma segura y además elegante mediante un ayudante de clase. Considerando que la necesidad de acceder a las instancias TDataLink puede ser algo eventualmente necesario en tus desarrollos, podrías definir un ayudante como el siguiente en tu biblioteca personal:
Código Delphi [-]
Type
  TDataSourceHelper = Class Helper For TDataSource
    Function FieldDataLink (Const AControl :TComponent) :TFieldDataLink;
  End;

//...

Function TDataSourceHelper.FieldDataLink (Const AControl :TComponent)
  :TFieldDataLink;
Var
  LLink :TDataLink;
Begin
  For LLink In DataLinks Do
    If (LLink Is TFieldDataLink) And
    (TFieldDataLink (LLink).Control = AControl) Then
      System.Exit (Pointer (LLink));

  Result := Nil;
End;
Lo anterior en esencia es equivalente a añadir un nuevo método público, de nombre FieldDataLink, a la clase TDataSource, pero sin modificar la unidad donde esta clase nativa se encuentra. FieldDataLink se encarga de buscar el objeto de clase TFieldDataLink que pertenezca a un control de captura dado —parámetro AComponent—. Con él, esta vez sí podrías llamar al método UpdateRecord desde el manejador de eventos OnKeyPress, como aparece en este ejemplo (ds1 es el DataSource, edPrice el DBEdit y da1 es el DataSet de almacenamiento):
Código Delphi [-]
procedure TForm1.edPriceKeyPress(Sender: TObject; var Key: Char);
begin
  If Key <> '/' Then
    System.Exit;

  ds1.FieldDataLink (edPrice).UpdateRecord;
  VCL.Dialogs.ShowMessage ('The value of the Price field is ' +
    da1.FieldByName ('Price').AsString);
  Key := #0;
end;
De este modo conseguimos que el texto introducido en el control data-aware se procese hacia el campo que se captura, antes de realizar alguna operación que necesite del campo actualizado.

NOTA: En caso de no contar con una versión de Delphi que soporte ayudantes de clases, puedes conseguir lo mismo con una clase TDataSourceAccess hija de TDataSource, poniendo en ella el nuevo método y accediendo a este mediante un molde de tipo sobre el DataSource. Un truco ya bastante conocido. Y de no estar soportado el For-In en tu compilador, esa parte del código puede usar un For normal.

Puede que esta no sea la solución más concisa, pero es similar a lo que yo haría si quisiera lograr lo mismo que tú.

Un abrazo más impuestos.

Al González.

Última edición por Al González fecha: 27-09-2016 a las 07:45:22.
Responder Con Cita