Ir para o conteúdo

Como associar dados a um item (Combobox ou Listbox)

Dois dos componentes mais usados em Delphi são as Combobox e as Listbox. São componentes muito semelhantes, na medida em que ambos contém uma lista de items que o utilizador pode escolher e selecionar, sendo que a diferença entre ambos é que na Listbox, a lista aparece sempre visível, enquanto na Combobox, a lista só é visível no momento da seleção, deixando apenas o item selecionado visível quando em "stand-by":

Formulário com uma ComboBox e uma ListBox

O que acontece por vezes é que, além da string que representa cada itens das listas, queremos guardar alguma outra informação, associada a cada item. Por exemplo, queremos guardar numa lista nomes de ficheiros, mas queremos guardar também o caminho onde esse ficheiro está guardado (sem que ele seja visível). Ou se quisermos guardar na lista nomes de pessoas, mas associar a sua idade para usar mais tarde. Ou ir mais longe, e junto com o nome da pessoa, guardar todo um conjunto de dados, como data de nascimento, sexo, nacionalidade, etc.

Claro, seria possível guardar qualquer outra informação numa variável/componente à parte, e manter uma associação através do índice da lista, mas a probabilidade de erro disto é grande, pois é necessário que de cada vez que se insira ou elimine um registo na lista, também se faça isso no "armazém" de dados, e com o cuidado adicional de manter os índices iguais entre as duas!

Felizmente, nada disto é necessário...

Ambos os componentes, bem como todos que usem o tipo TSrings para guardar dados, possuem a capacidade de guardar um objeto (TObject) junto com a string que constitui o texto.

A vantagem do TObject é que pode guardar qualquer tipo de dados, e como tal, qualquer que seja a informação que precisamos guardar junto com o item, pode ser convertida em TObject e guardada na lista. Basta que para isso se use uma funcionalidade chamada TypeCasting (o que permite converter entre tipos de dados em runtime).

Ex.1: Guardar o nome de um ficheiro (visível) e o caminho (invisível):

var
   FileName,FilePath:String;
.
.
.
   ComboBox1.AddItem (FileName, TObject (FilePath));  // O primeiro parâmetro é o item visível, o segundo é o objeto associado, neste caso, typecasted de string para TObject
.
.
.
// para usar os dados bastaria usar o seguinte:
   ShowMessage ('O caminho completo do ficheiro é:' + #13#10 + String (ComboBox1.Items.Objects[ComboBox1.ItemIndex]) + ComboBox1.Items [ComboBox1.ItemIndex]);
   // Agora, fez-se o typecast de TObject para String

Ex.2: Guardar um nome (visível) e a idade (invisível):

var
   Nome:String;
   Idade:Integer;
.
.
.
   combobox2.AddItem (Nome,TObject (Idade));  // Neste caso, a variável Idade foi typecasted de integer para TObject
.
.
.
// para usar os dados bastaria usar o seguinte:
   ShowMessage ('O(a) ' + ComboBox2.Items [ComboBox2.ItemIndex] + ' tem ' + IntToStr (Integer (ComboBox2.Items.Objects [ComboBox2.ItemIndex])) + ' anos.');
   // Agora, fez-se o typecast de TObject para Integer

Ex.3: Guardar um nome (visível) e um conjunto de dados associados (invisível):

type
   TDados=record
                Nome:String;
                DataNasc:TDate;
                Sexo:Char;
                Nacionalidade:String;
   end;
var
   Pessoa:TDados;
.
.
.
   ComboBox3.AddItem (Pessoa.Nome, TObject (Pessoa));  // Neste caso, a variável Pessoa foi typecasted de TDados para TObject
.
.
.
// para usar os dados bastaria usar o seguinte:
   Pessoa:=TDados (ComboBox3.Items. Objects [ComboBox3.ItemIndex]); // Agora, fez-se o typecast de TObject para TDados
   ShowMessage (Pessoa.Nome+#13#13#10+'Data de Nascimento: ' + Pessoa.DataNasc + #13#10 + 'Sexo: ' + Pessoa.Sexo + #13#10 + 'Nacionalidade: ' + Pessoa.Nacionalidade);

Assim, usando o mesmo índice (neste caso, foi usado a propriedade ItemIndex das Combobox para devolver o item selecionado), conseguimos aceder tanto ao item propriamente dito (o que é visível na lista para o utilizador) como ao objeto associado, através do uso de TypeCasting para converter de e para o tipo TObject.