DataModule Instanciavel
Gostaria de saber como faço para abrir o mesmo form instanciado, com um DataModule ligado a
ele pela unit, mas que o DataModule seja aberto noutra instancia.
Simulei um exemplo, criei um form (MDIChild) que chamo por meio do menu principal
dum formPrincipal(MDI) com um dbgrid ligado a um datasource e este ligado ao ClientDataSet
ligado ao Provider, ligado ao SQLQuery que por sua vez esta num DataModule.
O problema é que quando abro duas vezes o form (1) os dados do dbgrid se movem de acordo com
o form (2), ou seja o datamodule parece que não foi instanciado.
Isso vai gerar um problema pois quando fecho um dos forms abertos, e destruo a DataModule,
ao fechar o segundo form aberto a datamodule não existe mais e vai gerar um erro de memória.
Segue abaixo o código do exemplo.
A questão é: Tem como abrir uma instancia diferente da DataModule para cada form aberto?
Espero que alguém possa me ajudar.
No final do codigo explico o motivo de abrir o mesmo form duas vezes.
---- Código ----
Estou abrindo o Form Normal a partir do Form Principal deste forma:
procedure TFrPrincipal.acMnFormNormalExecute(Sender: TObject);
begin
FrFormNormal:=TFrFormNormal.Create(application); //Cria o Form
FrFormNormal.Show; //Mostra o form
end;
{ obs.: deixei desta forma para poder fazer a experiência, pois assim
posso abrir várias vezes o mesmo form. }
O form Normal esta assim:
uses UdmTeste;
{$R *.dfm}
procedure TFrFormNormal.FormCreate(Sender: TObject);
begin
inherited;
if dmTeste=nil then // se o datamodule não existe cria
dmTeste:=TdmTeste.Create(application); //Cria o data module
dmTeste.cdsTeste.Open; // abre o clientDataSet para mostrar os dados na grade
end;
{ obs.: no OnCreate do form (acima) é que está minha dúvida. }
procedure TFrFormNormal.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
inherited;
FrFormNormal := Nil; // Destroi o form da memoria
end;
procedure TFrFormNormal.btFecharClick(Sender: TObject);
begin
inherited;
Close; // fecha o form
end;
procedure TFrFormNormal.FormDestroy(Sender: TObject);
begin
inherited;
dmTeste.cdsTeste.Close; //Aqui vai dar erro pois o dmTeste.cdsteste
//já foi fechado no primeiro form aberto
dmTeste.Free; // Aqui vai dar o erro de memoria pois
dmTeste := Nil; // a dataModule já não existe
end;
{ Vai dar erro de memória no OnFormDestroy quando fechar o segundo form }
Motivo:
Criei um form cadastro que também serve de pesquisa para ele mesmo, esta pesquisa pode
ser usada em cadastros que precisam ser complementados com este dados. Por exemplo:
Tenho um cadastro de Funcionários nele á um campo Codigo do Setor este campo tem um botão
de pesquisa que abre uma tela de pesquisa de setor com uma grade com todos os setores
disponíveis ao clicar na grade o codigo do setor é passado para o cadastro de Funcionários.
Acontece que a tela de pesquisa é a mesma que tem no cadastro de Setor, explico, no form
cadastro de setor a duas abas uma com os dados dos setor (DADOS) outra aba (PESQUISA) com
um edit e um dbgrid (isto para evitar trafego na rede) sendo que ao clicar na grade abre
a aba DADOS trazendo do Banco de Dados apenas os dados do setor selecionado.
Já resolvi como chamar o de cadastro (MDIchild) e tb com chamar ele mesmo em ShowModal.
O problema é que se o cadastro de setor estiver aberto, e ao mesmo tempo estiver cadastrando
um funcionário e abrir a pesquisa de Setor (que é o mesmo form de Cadastro de Setor), devido
ao datamodule não ser instanciado (diferente) a grade de pesquisa é a mesma da pesquisa do
cadastro de setor, e ao fechar o form instanciado para pesquisa de setor no form de cadastro
de setor da erro de memória pois ao fecha-lo destruo o datamodule e ele já foi destroido
no form instanciado de setor para pesquisa.
Assim que resolver este problema posto o código inteiro pra no forum.
ele pela unit, mas que o DataModule seja aberto noutra instancia.
Simulei um exemplo, criei um form (MDIChild) que chamo por meio do menu principal
dum formPrincipal(MDI) com um dbgrid ligado a um datasource e este ligado ao ClientDataSet
ligado ao Provider, ligado ao SQLQuery que por sua vez esta num DataModule.
O problema é que quando abro duas vezes o form (1) os dados do dbgrid se movem de acordo com
o form (2), ou seja o datamodule parece que não foi instanciado.
Isso vai gerar um problema pois quando fecho um dos forms abertos, e destruo a DataModule,
ao fechar o segundo form aberto a datamodule não existe mais e vai gerar um erro de memória.
Segue abaixo o código do exemplo.
A questão é: Tem como abrir uma instancia diferente da DataModule para cada form aberto?
Espero que alguém possa me ajudar.
No final do codigo explico o motivo de abrir o mesmo form duas vezes.
---- Código ----
Estou abrindo o Form Normal a partir do Form Principal deste forma:
procedure TFrPrincipal.acMnFormNormalExecute(Sender: TObject);
begin
FrFormNormal:=TFrFormNormal.Create(application); //Cria o Form
FrFormNormal.Show; //Mostra o form
end;
{ obs.: deixei desta forma para poder fazer a experiência, pois assim
posso abrir várias vezes o mesmo form. }
O form Normal esta assim:
uses UdmTeste;
{$R *.dfm}
procedure TFrFormNormal.FormCreate(Sender: TObject);
begin
inherited;
if dmTeste=nil then // se o datamodule não existe cria
dmTeste:=TdmTeste.Create(application); //Cria o data module
dmTeste.cdsTeste.Open; // abre o clientDataSet para mostrar os dados na grade
end;
{ obs.: no OnCreate do form (acima) é que está minha dúvida. }
procedure TFrFormNormal.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
inherited;
FrFormNormal := Nil; // Destroi o form da memoria
end;
procedure TFrFormNormal.btFecharClick(Sender: TObject);
begin
inherited;
Close; // fecha o form
end;
procedure TFrFormNormal.FormDestroy(Sender: TObject);
begin
inherited;
dmTeste.cdsTeste.Close; //Aqui vai dar erro pois o dmTeste.cdsteste
//já foi fechado no primeiro form aberto
dmTeste.Free; // Aqui vai dar o erro de memoria pois
dmTeste := Nil; // a dataModule já não existe
end;
{ Vai dar erro de memória no OnFormDestroy quando fechar o segundo form }
Motivo:
Criei um form cadastro que também serve de pesquisa para ele mesmo, esta pesquisa pode
ser usada em cadastros que precisam ser complementados com este dados. Por exemplo:
Tenho um cadastro de Funcionários nele á um campo Codigo do Setor este campo tem um botão
de pesquisa que abre uma tela de pesquisa de setor com uma grade com todos os setores
disponíveis ao clicar na grade o codigo do setor é passado para o cadastro de Funcionários.
Acontece que a tela de pesquisa é a mesma que tem no cadastro de Setor, explico, no form
cadastro de setor a duas abas uma com os dados dos setor (DADOS) outra aba (PESQUISA) com
um edit e um dbgrid (isto para evitar trafego na rede) sendo que ao clicar na grade abre
a aba DADOS trazendo do Banco de Dados apenas os dados do setor selecionado.
Já resolvi como chamar o de cadastro (MDIchild) e tb com chamar ele mesmo em ShowModal.
O problema é que se o cadastro de setor estiver aberto, e ao mesmo tempo estiver cadastrando
um funcionário e abrir a pesquisa de Setor (que é o mesmo form de Cadastro de Setor), devido
ao datamodule não ser instanciado (diferente) a grade de pesquisa é a mesma da pesquisa do
cadastro de setor, e ao fechar o form instanciado para pesquisa de setor no form de cadastro
de setor da erro de memória pois ao fecha-lo destruo o datamodule e ele já foi destroido
no form instanciado de setor para pesquisa.
Assim que resolver este problema posto o código inteiro pra no forum.
Adrikal
Curtidas 0
Respostas
Emerson Nascimento
31/07/2007
crie uma variável do tipo TdmTeste na seção private do seu form e crie sua instância nesta variável.
por exemplo:
por exemplo:
uses
UDMTeste;
type
TFrFormNormal = class(...)
...
private
{private declarations}
local_DMTeste: TDMTeste;
public
{public declarations}
....
end;
implementation
{$R *.dfm}
procedure TFrFormNormal.FormCreate(Sender: TObject);
begin
inherited;
Application.CreateForm(TdmTeste, local_DMTeste);
local_DMTeste.cdsTeste.Open;
// agora você precisa redirecionar para local_DMTeste
// os componentes que estavam apontados para DMTeste
dbGrid.DataSource := local_DMTeste.Datasource;
// e precisa também alterar todas as referências
// de DMTeste para local_DMTeste
end;
procedure TFrFormNormal.FormDestroy(Sender: TObject);
begin
inherited;
local_DMTeste.cdsTeste.Close;
local_DMTeste.Free;
end;GOSTEI 0
Adrikal
31/07/2007
Valeu pela dica, vou testar depois informo o resultado
GOSTEI 0