Fórum Ajuda para carregar dado em um combobox #585010

18/08/2017

0

Olá pessoal, blz?!
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

Wilton Santos

Responder

Post 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

Rafael Bosco
Responder

Gostei + 2

Mais Posts

18/08/2017

Wilton Santos

Puxa vida que eficiência e agilidade que vocês têm, estou satisfeitíssimo com o tempo de resposta de vocês. Se continuar assim eu não vou cancelar nunca minha assinatura. Não testei o código ainda, mas vou testá-lo é qualquer coisa entro em contato.
Responder

Gostei + 1

18/08/2017

Fernando Gaspar

uhuuul show de bola!!
Responder

Gostei + 1

18/08/2017

Wilton Santos

Bom, estou aqui agora testando o codigo. Como você apenas postou o código sem nenhum comentário, eu entendi que a CLASS PROCEDURE deveria ir na Classe GRUPO, e no forme eu chamaria essa CLASS PROCEDURE para preencher o COMBO. Também entendi que para recuperar o valor do combo, eu deveria chamar a função getNivel. exemplo:

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.
Responder

Gostei + 0

18/08/2017

Rafael Bosco

Então, a class procedure, eu coloquei por que utilizo ela em modo STATIC, mas você pode chamar ela sendo uma procedure normal, e não precisar estar dentro da TGrupo necessariamente. Referente ao restante você entendeu a lógica muito bem.

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).
Responder

Gostei + 0

18/08/2017

Wilton Santos

Obrigado, mas não sei se você entendeu o meu problema:
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
Responder

Gostei + 0

18/08/2017

Wilton Santos

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.
Responder

Gostei + 0

21/08/2017

Rafael Bosco

Bom dia, acredito que eu tenho entendido hehe, vou colocar abaixo um exemplo, depois me diga se acertei ou não:

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.
Responder

Gostei + 0

21/08/2017

Wilton Santos

Wow!! Isso foi muito bom memso Rafael, Era disso que eu precisava. Embora eu não use FIREDAC nem crio meus SQLs desta forma, porque uso um FRAMEWORK genérico que faz meu CRUD, dá para ter uma excelente noção do funcionamento. Acredito que vou fechar o raciocínio perfeitamente aqui. Mas faltou só o finalzinho da minha postagem em: Wilton Santos| MVP Currículo
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:

Wilton Santos| MVP Currículo
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.
Responder

Gostei + 0

21/08/2017

Wilton Santos

OOps! A referencia do link deu errado aí, por favor, desconsidere o link e apenas continue lendo que eu repliquei a última postagem na citação.
Responder

Gostei + 0

22/08/2017

Rafael Bosco

Bom dia, ok, vamos lá, criei uma classe parecida com a sua e fiz um exemplo em execução:


      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
Responder

Gostei + 0

26/08/2017

Wilton Santos

Amigo, você acertou todas as vezes! Cada explicação foi muito útil. Com sua excelente atenção, conseguimos concluir este processo e tentei fazer estes métodos que você me passou de forma genérica porque temos mais de um COMBO com diferentes dados para trazer de listas, mas ficou me faltando detalhes para ter sucesso. O metodo GetLista até que ficou beleza e funcionando, mas para carregar o combo não consegui saber como acessar os campos de uma classe e listas genericos nem como acessar a mesma lista passada como variábel (AList) já preenchida do método getLista, para popular a combo.

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!
Responder

Gostei + 0

26/08/2017

Raimundo Pereira

Bom dia.
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.
Responder

Gostei + 0

26/08/2017

Wilton Santos

Porque eu odeio esses componentes na hora de fazer manutenção. Outra coisa, todas as vezes que alterar um campo no banco de dados esses componentes reclamam erro, eu sinceramente não gosto mesmo.

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.
Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar