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.