Ir al contenido


Foto

Datamodules en entorno MDI


  • Por favor identifícate para responder
12 respuestas en este tema

#1 jlopez

jlopez

    Newbie

  • Miembros
  • Pip
  • 6 mensajes

Escrito 16 noviembre 2011 - 09:21

Hola!
He encontrado algún hilo sobre el tema pero no termino de saber como hacerlo.
Creo tantos Tform como TDataModules pero no se como hacer referencia a uno u otro.
En el caso de los Tform los nombres se van 'bautizando' automáticamente (frm_child_1,frm_child_2) pero no sucede así con los datamodules.
Puede alguien orientarme en como acometer este problema?
  • 0

#2 pcicom

pcicom

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 267 mensajes
  • LocationMéxico

Escrito 16 noviembre 2011 - 10:35

No necesitas tantos DATAMODULES a menos que los manejes con controles de distintas BASES, por lo generar creas uno o dos DATAMODULOS y cuando requieras accesar a alguno en algun form..  unicamente lo declaras en el

[DELPHI]
implementation

uses
  datamodulo1, datamodulo2....  ;

[/DELPHI]

tal como se hace con la asociacion de Unidades..

En tu form..  te vas al menu File y das click en Use Unit..  y la seleccionas..


SALUDOS..


  • 0

#3 cadetill

cadetill

    Advanced Member

  • Moderadores
  • PipPipPip
  • 994 mensajes
  • LocationEspaña

Escrito 17 noviembre 2011 - 02:30

Buenas,

Lo malo delo que comenta pcicom es que si desde un form te mueves en una tabla, en todos los forms que usen esa tabla te estarás moviendo (si usas el mismo TDataSource, claro).

Lo que yo suelo hacer en aplicaciones MDI es declararme una propiedad en el formulario MDI del tipo del DataModule que quiera usar en esa pantalla y en el constructor  lo creo y asigno los DataSources y en el destructor lo destruyo. De esta manera, por mucho que me "mueva" en una pantalla, las demás ni se enteran.

También puedes tener el DataSource en el form MDI, con lo que en el constructor sólo tendrías que lincar los TDataSources con los TDataSets.

Espero te sirva

Nos leemos


  • 0

#4 jlopez

jlopez

    Newbie

  • Miembros
  • Pip
  • 6 mensajes

Escrito 17 noviembre 2011 - 06:03

Gracias por las respuestas...
Lo que quiero es exactamente lo que comenta cadetill, el problema es precisamente esa asignación, como hago referencia al tdatamodule?
He probado a hacer un array de tdatamodules pero sin éxito (lo tengo hecho para series de teechart y sus querys).
Creo que me estoy liando de mala manera... podrías mostrarme un ejemplo sencillo?
Te estaría eternamente agradecido... :)

  • 0

#5 cadetill

cadetill

    Advanced Member

  • Moderadores
  • PipPipPip
  • 994 mensajes
  • LocationEspaña

Escrito 17 noviembre 2011 - 10:40

Buenas

Veamos. Tenemos por un lado un DataModule llamado DM y por otro un MDIChild llamado Child (me complico en los nombre eh!! :D)

Bien, ahora en Child tienes que hacer algo así



delphi
  1. type
  2.   TChild = class(TForm)
  3.   ....
  4.   protected  // lo ponemos en protected por si hacemos herencia visual y esas cosas
  5.     property MyDM: TDM read FMyDM write FMyDM;
  6.   public
  7.     constructor Create(AOwner: TComponent); override;
  8.     destructor Destroy; override;
  9.   end;



Y ahora su implementación suponiendo que el TDatasource está en el formulario MDIChild y no en el TDataModule



delphi
  1. constructor TChild.Create(AOwner: TComponent);
  2. begin
  3.   inherited;
  4.  
  5.   FMyDM := TDM.Create(nil);
  6.   aDataSource.DataSet := FMyDM.aTable;
  7. end;
  8.  
  9. destructor TChild.Destroy;
  10. begin
  11.   if Assigned(Self.FMyDM) then FreeAndNil(Self.FMyDM);
  12.  
  13.   inherited;
  14. end;



Lo he puesto de cabeza. Espero te sirva.

Nos leemos
  • 0

#6 Sergio

Sergio

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1.092 mensajes
  • LocationMurcia, España

Escrito 17 noviembre 2011 - 11:04

Creo que deberias tener un solo datamodule si solo tienes una conexion a la base de datos, el datasource deberia estar en cada child, y el problema de como asignarle el datamodule, tanto en tiempo de diseño como de ejecución, es sencillo:

En tu aplicacion abre el código (Aplication, View Source code o algo asi aparece en el menú), tienes un gra "uses" y luego un procedimiento solo con su begin y un end, y dentro se inicializa el objeto aplication y luego se crean los forms que tengas con autocrete.

Lo que yo hago es editar ese codigo y le añado a mano una variable DM del tipo de tu datamodule (que ya deberia estar en el uses porque loo añadiste a tu aplicación), no recuerdo si va antes del procedure como VAR o dentro, y justo tras el begin la inicializo con DM:= TMyDataModule.create; y asi sé que esa variable esta siempre accesible en todos los forms de mi aplicacion.

Cuando diseño mi childform, le incluyo en el uses la unidad del datamodule y conecto los dataset con ese DM que, al ser una variable creada en el inicio de la aplicacion, siempre esta visible.

Asi funciona muy bien, quizas algun detalle no lo he explicado correcxtamente, es de memoria, pero es una forma sencilla de solventar el problema sin tener que memorizar ni crear datamodules durante la ejecucion de la aplicacion.

Si te interesa este sistema, te busco el trozo de codigo y te lo pego, es sencillo pero los detalles pueden complicarlo si no lo ves ya funcionando.
  • 0

#7 andres1569

andres1569

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 431 mensajes

Escrito 17 noviembre 2011 - 11:37

Hola

Si lo que te interesa es independizar cada formulario de los demás, es decir que usen cada uno su propia copia de cada DataSet, la solución de Cadetill me parece muy acertada, aunque te tocará picar más código y acordarte de tenerlo actualizado cada vez que añadas un Dataset al DataModule, y es buena idea, como dice Cadetill, para estos menesteres colocar un DataSource en el mismo formulario al que ligar los controles, de esta forma sólo tienes que ligar por código dicho DataSource al DataSet correspondiente, despreocupándote de los controles que tengas ligados al DataSource.

Otra opción que te propongo, si tienes a bien echarle un vistazo, son unos componentes de Al González, los MagiaData, que entre otros fines están pensados para crear este tipo de duplicaciones (o clonados) de forma que tú ligas los controles de un formulario a DataSets en un TDataModule, y los componentes MagiaData ya se encargan de generar copias independientes de cada DataSet para cada formulario, independizando los formularios. Te dejo el enlace de su bitácora donde hace poco anunció que son de libre distribución:

http://rescatandoade...a-descarga.html

Saludos
  • 0

#8 jlopez

jlopez

    Newbie

  • Miembros
  • Pip
  • 6 mensajes

Escrito 17 noviembre 2011 - 06:47

Carai! muchas gracias a los tres... estoy probando la opción de cadetill pero mi datasource esta en el datamodule...

Pensé que todo sería iterar por el array de components hacer un 'is tdbedit ' con findcomponent pero soy incapaz de realizar las asignaciones...

Alguna idea o muevo toooodos los datasources a los child?
  • 0

#9 cadetill

cadetill

    Advanced Member

  • Moderadores
  • PipPipPip
  • 994 mensajes
  • LocationEspaña

Escrito 18 noviembre 2011 - 01:50

Buenas,

Si no quieres mover los TDataSource al formulario, tendrás que tirar de RTTI. Tendrás que recorrer todos los componentes del fomulario y "preguntar" a cada componente si tiene la propiedad DataSource y, en caso de tenerla, asignársela.

El único "problema" que tiene ésto es si usas más de una tabla (DataSource) en el mismo formulario. Te tocará escoger el que menos componentes tenga y asignarle el DataSource "a mano" después de la función de asignación de DataSources.

La función de asignación del DataSource principal podría ser algo así



delphi
  1. procedure TCustomModalDbFrm.AssignDataSet;
  2.   procedure Assignar(Componente: TComponent);
  3.   var
  4.     idx: integer;
  5.     PropInfo: PPropInfo;
  6.     Component: TComponent;
  7.   begin
  8.     for idx := 0 to Componente.ComponentCount - 1 do
  9.     begin
  10.       Component := Componente.Components[idx];
  11.  
  12.       PropInfo := GetPropInfo( Component.ClassInfo, 'DataSource' );
  13.       if Assigned(PropInfo) then
  14.         SetObjectProp(Component, 'DataSource', MiDataSource);
  15.  
  16.       if Component.ComponentCount > 0 then
  17.         Assignar(Component);
  18.     end;
  19.   end;
  20. begin
  21.   Assignar(Self);
  22. end;



PPropInfo está definido en la unit TypInfo

Ahora, en el constructor de la clase, sólo te hace falta llamar a este método y seguidamente asignar "a pelo" los DataSources a los controles que no dependan de MiDataSource (en el caso de que los hubiera).

Espero te sirva

Nos leemos
  • 0

#10 jlopez

jlopez

    Newbie

  • Miembros
  • Pip
  • 6 mensajes

Escrito 18 noviembre 2011 - 02:50

Bueno... sin duda tu método es mejor a mi chapuza....

for i := ComponentCount-1 downto 0 do
  begin
    if Components[i] is tdbnavigator then
    begin      tdbnavigator(Components[i]).datasource:=tdatasource(fmydm.FindComponent(stringreplace(string(tdbnavigator (Components[i]).Name),'dbnv_','ds_', [rfReplaceAll, rfIgnoreCase])));
    end;
end;

Asi si el dbnavigator se llama dbnv_oe se q tengo q asignar al ds_oe.
Estaría bien poder solucionar esta chapuza estableciendo la asignacion con lo que se ha definido en  tiempo de diseño.
Es decir, que si al dbnavigator le he asignado el datasource dm_oe.ds_oe me evito un problema... el tema es que no soy capaz de sacar un dbnavitagor.datasource.tostring sin que de la lógica excepción....


Y si... tengo mas de un datasource en el mismo formulario... :(( Parece que lo he hecho todo mal...
  • 0

#11 cadetill

cadetill

    Advanced Member

  • Moderadores
  • PipPipPip
  • 994 mensajes
  • LocationEspaña

Escrito 18 noviembre 2011 - 03:59

Buenas

Yo no me complicaría la vida y pasaría los TDataSources al formulario. No te cuesta nada y la facilidad en el código la notarás.

No obstante, depende de la cantidad de componentes que tengas de cada DataSet. Si por ejemplo es un pantalla master-detail, y tienes dbEdits para la master y un grid para el detail, puedes hacer algo así:



delphi
  1. constructor TForm1.Create(aOwner: TComponent);
  2. begin
  3.   inherited;
  4.  
  5.   // asignamos un determinado dataset a todos los componentes del formulario
  6.   AssignDataSet;
  7.  
  8.   // asignamos los componentes individuales
  9.   navidatorDetail.DataSource := DataModule.DataSourceDetail;
  10.   grid.DataSource := DataModule.DataSourceDetail;
  11. end;



Espero te sirva

  • 0

#12 jlopez

jlopez

    Newbie

  • Miembros
  • Pip
  • 6 mensajes

Escrito 18 noviembre 2011 - 04:36

Nah! Definitivamente muevo los datasources al child y para asignar algo asi:


delphi
  1. for i := ComponentCount-1 downto 0 do
  2.   begin
  3. if Components[i] is tdatasource then
  4.     begin       

tdatasource(Components[i]).dataset:=tdataset(fmydm.FindComponent(stringreplace(string(tdxbardbnavigator(Components[i]).Name),'ds_','qry_', [rfReplaceAll, rfIgnoreCase])));
    end;
  end;
[/code]

Y arreglao...

Ahora el tema es que tengo un arbol de datamodules es decir tengo un dm_lgstc y un dm_lgstc_ul y en los childs utilizo ambos...
Los de nivel superior suelen ser maestro el tema es si tambien los "clono" o los uso compartidos.
Esto es mas una duda de implementación que técnica no se si continuamos con el hilo o abro uno nuevo...


Gracias a todos por la ayuda... :)
  • 0

#13 cadetill

cadetill

    Advanced Member

  • Moderadores
  • PipPipPip
  • 994 mensajes
  • LocationEspaña

Escrito 18 noviembre 2011 - 04:52

Buenas,

Abre otro hilo y explicate un poco mejor, que al menos yo no he terminado de entenderte :)

Nos leemos
  • 0




IP.Board spam blocked by CleanTalk.