Fórum Ajuda para carregar dado em um combobox #585010
18/08/2017
0
Preciso de ajuda: uso ENTITY em minhas classes, ou seja, são populadas de ATTRIBUTOS e busco no banco já os dados e no final já crio a lista. Exemplo:
-----------------------------
type
[TableName('pdg_Nivel')]
TNivel = class(TGenericEntity)
private
Fid: Integer;
FNivel: string;
procedure Setid(const Value: Integer);
procedure SetNivel(const Value: string);
public
[FieldName('Ni_id'), KeyField('Ni_id')]
property id : Integer read Fid write Setid;
[FieldName('Ni_Nivel')]
property Nivel : string read FNivel write SetNivel;
end;
TNivelObjList = TObjectList<TNivel>;
implementation--------------------------------
Tenho outra classe por nome GRUPO que precisará dos objetos desta classe (NIVEL). Quero apenas listar em uma combobox a lista de objetos desta classe NIVEL para recuperá-la ao salvar na outra classe (GRUPO). Veja a classe GRUPO:
type
[TableName('pdg_grupo')]
TGrupo = class(TGenericEntity)
private
FId: integer;
FidEstabl: integer;
FNombre: string;
FNivel: TNivelObjList; //veja onde quero trazer os dados
FCiclo: integer;
FSeccion_Ano: integer;
FTurno: string;
procedure setFId(const Value: integer);
procedure setFNombre(const Value: string);... etc
Tenho um form que possui o ccbNivel (combobox) e quero listar os níveis lá e depois salvar o id do Nivel dentro da classe GRUPO, tipo assim:
procedure TFrmGrupo.btnGuardarClick(Sender: TObject);
var
var_Nivel : integer;
Nomestr: string;
g : TGrupo;
begin
Nomestr := cbbNivel.Text +', '+ cbbCiclo.Text +', '+cbbSeccion.Text;
var_nivel := Integer(cbbNivel.Items.IndexOfObject(cbbNivel.ItemIndex));
g := TGrupo.Create;
with g do
begin
try
idEstabl := AEstabl;
Nombre := Nomestr;
Nivel := var_nivel;Acontece que não estou conseguindo, poderiam ajudar-me nesta rotina, por favor?
ERROS: 1-Nao consigo carregar o combo. 2-Ao tentar recuperar var_nivel me traz: Incompatible types: 'TObject' and 'Integer'
HELP, HELP!
Essa dúvida foi gerada a partir de um comentário no microexemplo TObjectList: Como trabalhar com coleções de objetos no Delphi
Wilton Santos
Curtir tópico
+ 0Post mais votado
18/08/2017
class procedure TSuaClasse.LoadAlgo(ACombo: TComboBox; AList: TSuaList);
var
Nivel, Loop: Integer;
begin
if AList.Count > 0 then
begin
ACombo.Items.Clear;
ACombo.Items.BeginUpdate;
for Loop := 0 to AList.Count - 1 do
begin
Nivel := AList[Loop].Nivel;
if Nivel > 0 then
ACombo.Items.AddObject('ID - ' + IntToStr(Nivel) , TObject(Nivel));
end;
ACombo.Items.EndUpdate;
end;
Depois para obter a informação digitada:
function GetNilvel: Integer;
begin
if (ComboBox.Items.Count > 0) and (ComboBox.ItemIndex > -1) then
Result := Integer(ComboBox.Items.Objects[ComboBox.ItemIndex])
else
Result := 0;
end;
Dicas:
1. NÃO UTILIZE o WITH em Classes e componentes, muito mais organizado você manter um padrão pelo nome correto!
2. Utilize o bloco TRY/FINALLY/END quando for criar as suas classes.
var
Grupo: TGrupo;
begin
Grupo := TGrupo.Create;
try
//Seu código;
finally
FreeAndNil(Grupo); //ou Destroy, ou Free
end;
end;
Rafael Bosco
Gostei + 2
Mais Posts
18/08/2017
Wilton Santos
Gostei + 1
18/08/2017
Fernando Gaspar
Gostei + 1
18/08/2017
Wilton Santos
procedure TFrmGrupo.btnGuardarClick(Sender: TObject);
var
Nomestr: string;
g : TGrupo;
begin
g := TGrupo.Create;
try
g.idEstabl := AEstabl;
g.Nombre := Nomestr;
g.Nivellista := getNivel; //recuperando o valor do combo.
finally
free
end;
end.
Detalhe: quero listar no combo o campo Nivel : String e recuperar o ID : integer para persistir no banco.
Fiz tudo de acordo, e continuo com o mesmo erro, nem chega a compilar:
[dcc64 Error] uFrmGrupo.pas(123): E2010 Incompatible types: 'System.Generics.Collections.TObjectList<uTNivel.Entity.TNivel>' and 'Integer'
Dê uma boa olhada na minha unit TGrupo, por favor, errei alguma coisa?:
unit uTGrupo.Entity;
interface
uses
uTGenericEntity, uTAtribEntity, uTValidacao, System.Generics.Collections,
uTNivel.Entity, System.SysUtils, Vcl.Dialogs, Vcl.StdCtrls;
type
[TableName('pdg_grupo')]
TGrupo = class(TGenericEntity)
private
FId: integer;
FidEstabl: integer;
FNombre: string;
FNivelObjList: TNivelObjList;
FCiclo: integer;
FSeccion_Ano: integer;
FTurno: string;
procedure setFId(const Value: integer);
procedure setFNombre(const Value: string);
procedure setFCiclo(const Value: integer);
procedure setFSeccion_Ano(const Value: integer);
procedure SetTurno(const Value: string);
procedure SetidEstabl(const Value: integer);
procedure setFNivelObjList(const Value: TNivelObjList);
constructor create;
destructor destroy; override;
public
class procedure CarregaComboNivel(ACombo: TcomboBox;
AList: TNivelObjList); static;
[FieldName('grp_id'), KeyField('grp_id')]
property Id : integer read FId write setFId;
[FieldName('grp_establ')]
property idEstabl : integer read FidEstabl write SetidEstabl;
[FieldName('grp_nombre')]
[TValidacao_NotNulll('Ingrese el Nombre')]
property Nombre : string read FNombre write setFNombre;
[FieldName('grp_nivel')]
property NivelLista : TNivelObjList read FNivelObjList write setFNivelObjList;
[FieldName('grp_ciclo')]
property Ciclo : integer read FCiclo write setFCiclo;
[FieldName('grp_seccionAno')]
property Seccion_Ano : integer read FSeccion_Ano write setFSeccion_Ano;
[FieldName('grp_turno')]
property Turno : string read FTurno write SetTurno;
end;
TGrupoList = TList<TGrupo>;
implementation
{ TGrupo }
procedure TGrupo.SetTurno(const Value: string);
begin
FTurno := Value;
end;
class procedure TGrupo.CarregaComboNivel(ACombo: TcomboBox;
AList: TNivelObjList);
var
i, Registro : Integer;
begin
if AList.Count > 0 then
begin
Acombo.items.clear;
ACombo.Items.BeginUpdate;
for i := 0 to AList.Count -1 do
begin
Registro:= AList[i].id;
if Registro > 0 then
ACombo.Items.AddObject('id -'+IntToStr(Registro), TObject(Registro));
end;
ACombo.Items.EndUpdate;
end;
end;
constructor TGrupo.create;
begin
//criando a lista de objetos e adicionando o nivel
FNivelObjList:= TNivelObjList.Create();
FNivelObjList.add(TNivel.Create);
end;
destructor TGrupo.destroy;
begin
//destruir a lista de objetos
FreeAndNil(FNivelObjList);
inherited;
end;
procedure TGrupo.setFCiclo(const Value: integer);
begin
FCiclo := Value;
end;
procedure TGrupo.setFId(const Value: integer);
begin
FId := Value;
end;
procedure TGrupo.setFNivelObjList(const Value: TNivelObjList);
begin
FNivelObjList := Value;
end;
procedure TGrupo.setFNombre(const Value: string);
begin
FNombre := Value;
end;
procedure TGrupo.setFSeccion_Ano(const Value: integer);
begin
FSeccion_Ano := Value;
end;
procedure TGrupo.SetidEstabl(const Value: integer);
begin
FidEstabl := Value;
end;
end.
Gostei + 0
18/08/2017
Rafael Bosco
Referente ao seu erro, em determinado momento, parece que está buscando o valor INTEGER invés da lista em si, verifique a variavel FNivelObjList (é ela que você tem que passar como parâmetro para carregar o combobox).
Gostei + 0
18/08/2017
Wilton Santos
Vamos para outro exemplo, vou tentar ser mais claro. Se eu tenho uma classe de PESSOAS por exemplo, e essa pessoa tem ENDEREÇO, então posso criar uma classe chamada TEndereco que faz parte de TPessoa. Então essa classe TEndereco servira para chamar os dados de Endereços de qualquer coisa(O TODO) da qual o ENDEREÇO é parte. Mas veja bem, quero consumir essa classe como uma lista de endereço trazido do banco para me atender em TPessoa.
Quando eu estou registrando uma nova pessoa, eu vou dizer para minha classe pessoa chamar a classe endereço e guardar endereço. quando eu precisar consultar uma pessoa, essa classe TPessoa vai dizer para a classe endereço: Hei, TEndereco traz o endereço desta pessoa para mim lá do banco por favor... jejeje...e por que?
Porque a classe TPessoa tem que estar assim:
type TPessoa = class(TObject) Fid : integer; FNome : string; FEndereco : TEndereco; //O relacionamento de classes aqui seria de "Parte e Todo" FContato : TContato // E tambem posso fazer isso para contatos e outras coisas mais... end.
Cada vez que eu chamar essas classes, nem precioso saber quem esta chamado ela, se é TPessoa ou se é TEstabelecimento ou se é TFornecedor, etc... a classe vai simplesmente trazer os dados ou persistir os dados no banco, de acordo com a necessidade de cada um, mas sempre se comportara do mesmo modo. Fornecer e persistir informações no Banco de Dados. TAMBÉM nem importa para onde eu quero levar esses dados, se é para um TEDIT ou um TCOMBOBOX ou qualquer outro componente, isso já seria coisa do FORM ou de uma FACTORY, mas não da classe TEndereco ou das classes que a consome.
PROBLEMA 1: De que forma posso (SALVAR) os dados de FEndereco : TEndereco na Tabela Pessoas do banco, preencheendo todos os campos de endereço, seja integer, string, etc... através da Classe TEnderço, pois o banco não possui nenhum campo do tipo TList, uai.
PROBLEMA 2: De que forma posso trazer uma consulta de Pessoas (TPessoa) do banco, consumindo a classe TEndereco e mostrar, seja em edits, combos, ou grids todos os dados do endereço.
No meu caso, apenas quero trazer do banco todos os campos de Nivel que possui apenas Id e Nome, e escolher um deles da lista de Nivel mostrados no combobox e salvar o id dele no banco através da classe TGrupo. Porque Grupo possui Nivel. Simples assim.
Fui mais claro agora ou compliquei, kkkk?
No aguardo, obrigado.
Mais de um ano de Cliente e nunca precisei tanto de voces como agora. Já dei uma explorada lá no Hélio Carlos, porque realmente tenho um dasafio.
Moro na Argentina, Buenos Aires e tenho uma missao árdua esse mês.
Por favor, tenham paciencia comigo. kkk
Gostei + 0
18/08/2017
Wilton Santos
Mas no meu caso prático de GRUPO e NIVEL, precisa ser lista, porque existem mais de um nivel no registro de NIVEL e eu preciso escolher um só e gravar no banco de dados dizendo que aquele GRUPO é daquele NÍVEL. E ainda tem outros tipos como SECCION e CICLO, mas se aprender fazer o NIVEL o resto será igual.
Gostei + 0
21/08/2017
Rafael Bosco
1. Criei as classes TEndereco e TPessoa, juntamente com uma classe statica para as SQL's (Deixo o método como static para que eu não precise instaciar a classe, já que será utilizada apenas para obter uma string).
TSQLControl = class sealed (TObject)
public
class function InsertPessoaSQL: String; static;
class function InsertEnderecoSQL: String; static;
class function SelectPessoaSQL: String; static;
end;
TEndereco = class sealed (TObject)
private
FUF: String;
FCEP: String;
FNumero: String;
FComplemento: String;
FCidade: String;
FRua: String;
FId: Integer;
procedure SetCEP(const Value: String);
procedure SetCidade(const Value: String);
procedure SetComplemento(const Value: String);
procedure SetNumero(const Value: String);
procedure SetRua(const Value: String);
procedure SetUF(const Value: String);
procedure SetId(const Value: Integer);
public
function Insert: Boolean;
property Id: Integer read FId write SetId;
property CEP: String read FCEP write SetCEP;
property Rua: String read FRua write SetRua;
property Numero: String read FNumero write SetNumero;
property Complemento: String read FComplemento write SetComplemento;
property Cidade: String read FCidade write SetCidade;
property UF: String read FUF write SetUF;
end;
TPessoa = class sealed (TObject)
private
FId: Integer;
FNome: String;
FEndereco: TEndereco;
procedure SetEndereco(const Value: TEndereco);
procedure SetId(const Value: Integer);
procedure SetNome(const Value: String);
public
function Insert: Boolean;
function Select: Boolean;
property Id: Integer read FId write SetId;
property Nome: String read FNome write SetNome;
property Endereco: TEndereco read FEndereco write SetEndereco;
destructor Destroy; override;
end;
2.Após criada as classes, criei 1 Método de INSERT para a Classe TEndereco, e 2 métodos na classe TPessoa, e 3 funções statics na classe TSQLControl.(A Classe TQuery descrita abaixa usei para simular a sua conexão com o banco de dados (FireDAC, DBExpress, Zeos, etc..), no meu caso eu utilizo o FireDAC).
{ TEndereco }
function TEndereco.Insert: Boolean;
var
Query: TQuery;
begin
FDConnection.StartTransaction;
try
Query := TQuery.Create;
try
Query.AddSQL(TSQLControl.InsertEnderecoSQL);
Query.ParamByInt('ID', FId);
Query.ParamByStr('RUA', FRua);
Query.ParamByStr('NUMERO', FNumero);
Query.ParamByStr('CEP', FCEP);
Query.ParamByStr('COMPLEMENTO', FComplemento);
Query.ParamByStr('CIDADE', FCidade);
Query.ParamByStr('UF', FUF);
Query.ExecSQL;
FDConnection.Commit;
Result := True;
finally
FreeAndNil(Query);
end;
except
on E: Exception do
begin
FDConnection.RollBackTransaction;
raise Exception.CreateFmt('Erro ao inserir os dados de endereço! Motivo: ' + E.Message, []);
end;
end;
{ TPessoa }
destructor TPessoa.Destroy;
begin
if Assigned(FEndereco) then
FEndereco.Destroy;
inherited;
end;
function TPessoa.Insert: Boolean;
var
Query: TQuery;
begin
FDConnection.StartTransaction;
try
Query := TQuery.Create;
try
Query.AddSQL(TSQLControl.InsertPessoaSQL);
Query.ParamByInt('ID', FId);
Query.ParamByStr('NOME', FNome);
Query.ParamByInt('IDENDERECO', FEndereco.FId);
Query.ExecSQL;
Result := True;
finally
FreeAndNil(Query);
end;
except
on E: Exception do
begin
FDConnection.RollBackTransaction;
raise Exception.CreateFmt('Erro ao inserir os dados da classe: ' + Self.ClassName + '! Motivo: ' + E.Message, []);
end;
end;
end;
function TPessoa.Select: Boolean;
var
Query: TQuery;
begin
Query := TQuery.Create;
try
Query.AddSQL(TSQLControl.SelectPessoaSQL);
Query.ParamByInt('ID', FId);
Result := Query.OpenedSQL;
if Result then
begin
FEndereco := TEndereco.Create;
FEndereco.FUF := Query.FieldByStr('UF');
FEndereco.FCidade := Query.FieldByStr('CIDADE');
FEndereco.FRua := Query.FieldByStr('RUA');
FEndereco.FNumero := Query.FieldByStr('NUMERO');
FEndereco.FComplemento := Query.FieldByStr('COMPLEMENTO');
FEndereco.FCEP := Query.FieldByStr('CEP');
FNome := Query.FieldByStr('NOME');
end;
finally
Query.CloseSQL;
FreeAndNil(Query);
end;
end;
{ TSQLControl }
class function TSQLControl.InsertEnderecoSQL: String;
begin
Result := 'INSERT INTO TENDERECO (ID, RUA, NUMERO, CEP, COMPLEMENTO, CIDADE, UF)VALUES' + sLineBreak +
'(:ID, :RUA, :NUMERO, :CEP, :COMPLEMENTO, :CIDADE, :UF)';
end;
class function TSQLControl.InsertPessoaSQL: String;
begin
Result := 'INSERT INT TPESSOA (ID, NOME, IDENDERECO)VALUES' + sLineBreak +
'(:ID, :NOME, :IDENDERECO)';
end;
class function TSQLControl.SelectPessoaSQL: String;
begin
Result := 'SELECT * FROM TPESSOA PES INNER JOIN TENDERECO ENDER ON PES.IDENDERECO = ENDER.ID' + sLineBreak +
'WHERE PES.ID = :ID';
end;
Como pode observar no código acima, eu criei um campo na tabela TPESSOA para representar a identificação do endereço do registro (IDENDERECO), ou seja, quando eu buscar os dados da TPESSOA, como saberei qual é o endereço dela? Será pelo campo ID na tabela TENDERECO.
Por isso no select eu coloquei um INNER JOIN (significa que se a Query trazer algum resultado, obrigatoriamente existe os registros em ambas as tabelas).
Após realizado o SELECT, eu crio a classe TENDERECO através da variavel FENDERECO, e atribui as suas propertys aos fields da query, e no DESTROY da classe, eu verifico se a classe ta instanciada, caso tiver eu destruo para que não ocorra leak de memória.
A classe TEndereco não é uma lista, é uma classe normal, que carrega somente no select da classe TPessoa, após isso você pode vincular em qualquer componente que você deseja, conforme exemplo abaixo:
procedure TFMain.LoadEndereco;
var
Pessoa: TPessoa;
begin
Pessoa := TPessoa.Create;
try
Pessoa.Id := 1; //Apenas para simular um ID de um registro qualquer
if Pessoa.Select then
begin
EdtNomePessoa.Text := Pessoa.Nome;
EdtEnderecoRua.Text := Pessoa.Endereco.Rua;
EdtEnderecoNumero.TExt := Pessoa.Endereco.Numero;
EdtEnderecoCEP.Text := Pessoa.Endereco.CEP;
EdtEnderecoCidade.Text := Pessoa.Endereco.Cidade;
EdtEnderecoUF.Text := Pessoa.Endereco.UF;
EdtEnderecoComp.Text := Pessoa.Endereco.Complemento;
end
else
ShowMessage('Cadastro não encontrado!');
finally
Pessoa.Destroy;
end;
end;
No momento do INSERT da classe TPESSOA, faça o INSERT da classe TENDERECO, criando a mesma e atribuindo as suas propertys aos seus componentes desejados e chamando o método INSERT de ambas.
Se tiver alguma dúvida referente a tudo isso aí, só avisar! Abraços.
Gostei + 0
21/08/2017
Wilton Santos
www.devmedia.com.br/webcurriculo/?nome_space=wilton-santos-1 18 ago 2017, quando eu me referi ao meu caso prático com relação à lista de Objetos. Ainda estou apanhando "praquele troço", jejeje. Replico aqui o que escrevi:
18 ago 2017
OBS: Acho que neste meu caso de TEndereco não seria uma lista, porque cada registro das classes consumidores só possuirão um unico endereço e não muitos.
Mas no meu caso prático de GRUPO e NIVEL, precisa ser lista, porque existem mais de um nivel no registro de NIVEL e eu preciso escolher um só e gravar no banco de dados dizendo que aquele GRUPO é daquele NÍVEL. E ainda tem outros tipos como SECCION e CICLO, mas se aprender fazer o NIVEL o resto será igual.
Quero listar no meu combobox todos os campos "Nivel" da Lista, que é uma STRING, repito, é uma STRING. E quando selecionar essa STRING, quero gravar no BANCO DE DADOS o "ID" referente àquela STRIING que é um inteiro. É aí que estou apanhando. como localizar o ID e outros dados relacionados na lista? Por exemplo, se eu tivesse um valor do tipo DOUBLE relacionado na lista, como poderia recuperar ele? O meu problema atual é só o ID e a STRING, se quiser deixar esse exemplo do DOUBLE para depois tudo bem.
De antemão te agradeço. Vou recomendar o site aos meus amigos aqui na Argentina. Você melhoraram muito mesmo.
Parabéns pelas respostas e conteúdos.
Aguardo resposta.
Abraços.
Gostei + 0
21/08/2017
Wilton Santos
Gostei + 0
22/08/2017
Rafael Bosco
TPessoa = class
private
FId: Integer;
FNivel: String;
procedure SetId(const Value: Integer);
procedure SetNivel(const Value: String);
public
property Id: Integer read FId write SetId;
property Nivel: String read FNivel write SetNivel;
end;
1. Primeiro alimento a Lista: TList<TPessoa>, que é a lista de objetos do TPessoa:
function TFMain.GetList: TList<TPessoa>;
var
Pessoa: TPessoa;
begin
Result := TObjectList<TPessoa>.Create;
try
//Apenas para simular um select no banco de dados...
Pessoa := TPessoa.Create;
Pessoa.Id := 42;
Pessoa.Nivel := 'WILSON';
Result.Add(Pessoa);
Pessoa := TPessoa.Create;
Pessoa.Id := 119;
Pessoa.Nivel := 'RAFAEL';
Result.Add(Pessoa);
except
Result.Free;
end;
end;
2 .No form, ou qualquer unit que você esteja trabalhando, crie um método para carregar o combobox com os registros de TPessoa:
procedure TFMain.LoadCombo(ACombo: TComboBox; AList: TList<TPessoa>);
var
Loop: Integer;
Pessoa: TPessoa;
begin
if AList.Count > 0 then
begin
try
ACombo.Items.Clear;
ACombo.Items.BeginUpdate;
for Loop := 0 to AList.Count - 1 do
begin
Pessoa := AList[Loop];
if Pessoa.Id > 0 then
ACombo.Items.AddObject('Nivel - ' + Pessoa.Nivel , TObject(Pessoa.Id));
end;
ACombo.Items.EndUpdate;
finally
AList.Destroy; //liberar a lista da memória
end;
end;
end;
3. Para obter o ID da classe TPessoa que está dentro do combobox:
function TFMain.GetIdComboBox: Integer;
begin
if ComboBox1.ItemIndex > -1 then
Result := Integer(ComboBox1.Items.Objects[ComboBox1.ItemIndex]);
end;
Simulei a apresentação do registro através do clique de um botão, da seguinte forma:
if ComboBox1.ItemIndex > -1 then
ShowMessage(IntToStr(GetIdComboBox));
Abaixo, alguns prints mostrando como ficou:
Print 1
Print 2
Print 3
Abraços, espero que eu tenha acertado agora kk
Gostei + 0
26/08/2017
Wilton Santos
veja como ficou meus metodos genericos:
function TFrmGrupo.getLista<T>(AList : TList<T>): TList<T>;
var
obj: T;
begin
AList:= TList<T>.Create;
try
obj:=T.Create();
FPersistence.getListDaBase<T>(AList); //esse metodo ja adiciona os items na lista
Result := Alist;
finally
AList.Free;
DestruirItensLista<T>(Alist);
obj.free;
end;
end;
//CARREGAR O COMBO
procedure TFrmGrupo.CarregaCombo<T>(ACombo: TcomboBox; AList: TList<T>);
var i, n : Integer;
Classe : T;
begin
if not Assigned(classe) then
begin
Classe:= T.Create();
end else
begin
Alist := getLista<T>(Alist);
// if Alist = nil then
// Alist := TList<T>.Create
// else
if AList.Count > 0 then
begin
try
Acombo.items.clear;
ACombo.Items.BeginUpdate;
for i := 0 to AList.Count -1 do
begin
Classe:= AList[i];
// if Classe > 0 then //AQUI TERIA QUE ACESSAR O CAMPO id
ACombo.Items.Addobject('teste1', TObject(Classe)); ////AQUI TERIA QUE ACESSAR O CAMPO Descrição e também o id
end;
ACombo.Items.EndUpdate;
finally
// Listas e Classes sao destruidas no metodo getLista
if Assigned(classe) then FreeAndNil(Classe);
if Assigned(Alist) then FreeAndNil(Alist);
end;
end;
end;
end;
Se tiver alguma ideia, agradeço.
Valeu brother!
Gostei + 0
26/08/2017
Raimundo Pereira
Porquê não usa o dbloockupcombobox.
Usando as propriedades listfild.
Nele você pode vizualizar varias colunas, basta separar por campo1;campo2 e etc..
Na hora de retornar o campo basta pegar o campo id.
Gostei + 0
26/08/2017
Wilton Santos
Prefiro ter meu framework e minhas classes do que encher um Data Module de componentes. Já sofri demais com isso. Depois da nova RTTI e Generics não quero isso nunca mais.
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)