PDA

Ver la Versión Completa : Asignar TField a TDBLookupList en T.ejecución


Bauhaus1975
28-10-2008, 11:13:06
Hola, tengo un TDBLookupList (realmente es un TJvDBLookupList, de las Jedi), conectado a un data source, y este a su vez conectado a un TIBQuery (que hace de DataSet), resulta que quiero llenar la lista con uno de los campos del resultado de la query. No sé bien cómo hacerlo.
Estoy intentando asignar un campo (TField) de la query en el datasource en tiempo de ejecución. Pero no funciona, slata excepción en la linea (2ª) del 'FindField'

prueba := TField.Create(self.TJvDBLookupList); // prueba es de tipo TField
prueba := DataModule.ibQuery.FindField('TIPO');
form1.TJvDBLookupList.Field.Assign(prueba);

¿Alguien puede guiarme un poco?
Muchas gracias y un saludo.

coso
28-10-2008, 11:46:33
Hola, antes que nada, si findfield te devuelve un objeto tipo TField, no deberias crear prueba antes, pues el findfield sobreescribira el recien creado. De igual manera, si ahora mismo hicieses un prueba.free, estarias liberando DataModule.ibQuery.FindField('TIPO'). Es raro que te salte una excepción, pues si TIPO existe te tendria que devolver nil. Es posible que ibQuery no este asignado antes de hacer el findfield? prueba de hacer:


var
prueba : TField;
begin
if not Assigned(DataModule.ibQuery) then ShowMessage('');
prueba := DataModule.ibQuery.FindField('TIPO');
form1.TJvDBLookupList.Field.Assign(prueba);


si nos indicas cual es el mensaje de la excepción, quiza te podamos ayudar mejor. saludos.

Bauhaus1975
29-10-2008, 11:42:42
Hola coso, gracias por tu atención.
He probado la sentencia 'if not Asign' y me lanza la excepción 'Read of Address', parece que hay problemas de acceso al ibQuery, aunque desconozco por qué. He probado a llamar a un método público del DataModule y no da error de acceso. Este DataModule dónde se encuentra la query tiene definido otro DataModule en la directiva 'interface', el cual contiene la conexión a la base de datos y un TIBTransaction al que se conectan las queries (aunque no creo que esto sea problema).

Otra cosa, el ibQuery tiene definida una sentencia SQL, pero luego a parte tiene definido un campo, el cual es uno de los campos obtenidos en la sentencia, para alimentar posteriormente la lista. Aunque no sé si esto es correcto o la mejor manera, ya que no tengo mucha experiencia programando este tipo de aplicaciones.

He seguido probando cosas, pero no sé que puede estar pasando.
¿Alguna idea?

coso
29-10-2008, 17:45:24
Hola, yo simplificaria todo a un unico datamodule (para eso esta este tipo de form, para no tener desperdigados todos los componentes de base de datos). Es probable que haya algun lio por alli (forms con el mismo nombre y diferentes componentes, por ejemplo, cosas asi) Por otra banda, si te da un error de read address, lo mas probable es que no este asignado o bien datamodule (que no este creado en tiempo de ejecucion) o bien que hayas liberado el ibQuery. Prueba if not assigned(Datamodule) then ShowMessage(''). Creo que debe ser eso, que no tienes creada la form Datamodule al llegar a este punto. Saludos.

Bauhaus1975
30-10-2008, 09:41:07
Hola de nuevo, he probado lo que me dices y nada.
Parece que todo está bien asignado, además todos los objetos (datasource, query) accedo sin problemas en tiempo de ejecución. El error ocurre al llamar a esa sentencia 'Assign', así que seguiré investigando.
Gracias.

coso
30-10-2008, 09:56:23
Hola, no es assign() es assigned(). La primera copia dos objetos. La segunda comprueba que el argumento pasado como puntero no sea null. Saludos.

Bauhaus1975
30-10-2008, 12:03:06
Hola, me refería a la linea:
form1.TJvDBLookupList.Field.Assign(prueba);
Que es donde salta la excepción...

coso
30-10-2008, 12:07:30
¿Son de los mismos tipos?¿o Fields es TFieldList? Si se puede acceder a Field de manera array (Field[0]) entonces son distintos tipos. De todas maneras, prueba con una asignacion directa (form1.TJvDBLookupList.Field = prueba) y comprueba antes si prueba no es null (if prueba = nil then showmessage(''))

Bauhaus1975
30-10-2008, 16:22:45
Son TField.
La sentencia form1.TJvDBLookupList.Field = prueba; no puede ejecutarse porque '.Field' es de sólo lectura...

coso
30-10-2008, 17:38:37
Si es de solo lectura...tampoco le tendrias que poder hacer un assign en teoria. De todas maneras, has comprobado que prueba no sea nil antes del assign? ¿Y para que sirve la propiedad .Field? si es de solo lectura, probablemente sera por algun motivo.

coso
30-10-2008, 17:40:36
Es extraño que sea tipo TField. Si TJvDBLookupList es analogo al TDBLookupListBox, tendria que ser un tipo string...

EDITO : TDBLookUpListBox.DataField tambien es de tipo TField.

Bauhaus1975
31-10-2008, 21:11:41
Hola de nuevo. Algo he avanzado al menos.
Resulta que cómo sigo bastante 'verde' con Delphi no había visto la propiedad 'DataField', la cual he usado para signar el campo (Field) 'TIPO' de la query. Ahora al menos esta sentencia no da problemas. Otra cosa: He cambiado el TJvDBLookupList por un TDBListBox, ya que sólo necesito mostrar todos los valores de un campo en la lista y no quiero complicarme.

Lo peor es que (ahora) no soy capaz de hacer que se carguen los datos en la lista. He revisado y todo parece bien conectado.

¿Hay algo que me falta o algún paso es incorrecto?
Añado la sección de código implicada:


Código Delphi [-] (http://www.clubdelphi.com/foros/#)
{
-La idea es cargar en la lista lo almacenado en el campo 'Tipo' de la tabla 'Tipos'-
dbListTipos -> Lista asociada al sgte DataSource
dsTipos -> Asociado a la query
ibqObtenerTipos -> la query (SELECT DISTINCT(Tipo) as Tipo FROM Tipos)
}
self.dbListTipos.ReadOnly := true;
self.dbListTipos.DataField := 'TIPO';
// Ejecutamos la query
try
with DM.dmPrincipal do
begin
// Preparamos la transacion
if (ibtPrincipal.InTransaction) then
if (not ibtPrincipal.Active) then
begin
ibtPrincipal.StartTransaction;
ibtPrincipal.Active:=true;
ibtPrincipal.Rollback;
end;
// Realizamos la petición de datos
self.dsTipos.DataSet.Close;
dmComunData.ibqObtenerTipos.Close;
dmComunData.ibqObtenerTipos.Active := true;
dmComunData.ibqObtenerTipos.Open;

self.dsTipos.DataSet.Open();
// Mostramos el formulario
self.ShowModal; // Al mostrar el formulario no se carga nada
end;
finally
showmessage('ERROR DE BBDD');
end;






Haciendo un debug, he visto que la query efectivamente devuelve los registros existentes en la BBDD, pero la lista no carga nada...

Gracias de nuevo y un saludo.

coso
31-10-2008, 21:52:22
...creo que te estas confundiendo...Si tu lo que quieres es asignar a un campo uno escogido entre varios valores estaticos, entonces el DBListBox te funciona correctamente : DataField, campo a modificar; DataSource, de donde es el campo, Items, valores a escoger. Si lo que quieres, como parece que es el caso, es modificar un campo de cierto dataset con los valores de otro campo de otra dataset, entonces debes usar DBLookUpListBox, donde DataField, campo a modificar, DataSource, source a modificar, ListField, campo a mostrar en la lista, ListSource, de donde se sacan los campos a mostrar en la lista, KeyField, campo que realmente se pasa de la lista mostrada al DataField. Por ejemplo:

ListSource := src_clientes;
ListField := 'nombre_cliente';

KeyField := 'id_cliente';

DataSource := src_facturas;
DataField := 'id_pagador';

esto me permetiria escoger entre los nombre_cliente de src_clientes, para poner el valor de id_cliente en id_pagador de src_facturas...creo que esto ultimo es lo que buscas.

EDITO: se supone q datasource lo tienes asignado.

Bauhaus1975
01-11-2008, 09:41:58
Me parece que no es caso de uso para un DBLookUpListBox (aunque tampoco estoy seguro). Imagina la tabla clientes que mencionas, pues simplemente quiero mostrar en una lista todos los nombres de clientes (campo Nombre), para seleccionar uno.

Para eso tengo un TIBQuery (el DataSet), un DataSource conectado y el TDBListBox conectado a este último.
En el mensaje anterior tengo la sección de código como intento abrir el data set etc para alimentar los datos pero no sale nada. No sé si realmente tengo que usar otro componenete como dices o hacer algo que no estoy haciendo.
Saludos.

coso
01-11-2008, 11:17:47
No te sale nada porque mediante datafield, datasource no estas alimentando la lista, lo que haces es indicar que campo vas a modificar. Para que quieres escoger algun cliente? para modificar el campo de otra base de datos no? Con el DBListBox por ejemplo yo podria hacer

DBListBox.DataSource := unidades;
DBListBox.DataField := 'TIPO_UNIDADES';
DBListBox.Items.Text := 'kgs litros dm mm';

y entonces al escoger del DBListBox, me canviaria el campo 'TIPO_UNIDADES' del datasource UNIDADES. El DBLookUpComboBox hace lo mismo, solo que escogeria la lista de otra base de datos, que creo que es lo que quieres hacer tu. Releetelo con calma y ya veras que es eso ;) saludos.

Bauhaus1975
02-11-2008, 13:11:49
Hola, tenías toda la razón.
He usado un TDBLookupList, he asignado las propiedades 'LookupField' y 'LookupDisplay' y ha funcionado. Sin duda, mi falta de conocimientos me hábía hecho confundir la funcionalidad del TDBListbox y el TDBLookupList. Además de querer haber asginado el campo, motivo de inicio de este post.
Así que muchas gracias por tu paciencia porque de no ser por tu ayuda me hubiera costado salir adelante.
Gracias y un saludo.

coso
02-11-2008, 13:28:24
de nada ;) para eso esta el foro