A veces, lo que parece más sencillo no lo es. A simple vista, rellenar un ComboBox/ListBox con los datos que provienen de una base de datos y que cada elemento mostrado tenga un Valor que “nada” tenga que ver con lo mostrado (el típico caso Nombre/Id, Clave/Valor, Pais/Código ISO,…) se hace con unos cuantos clicks (gracias al infame ADO.NET).
Sin embargo, cuando el caso es el contrario (lo rellenamos con cualquier otra cosa que no sea mediante ADO.NET), es un poco más complejo:
En el diseñador, los items del ComboBox/ListBox que se añaden son lineas de texto. Por tanto, a primera vista, no podemos hacer nada de lo que hablamos arriba. Sin embargo, echándole un vistazo a las funciones del ComboBox/ListBox encontramos algo curioso: tanto la propiedad SelectedItem como la función Add de la ObjectCollection Items aceptan un object en lugar de string como creíamos por culpa del diseñador.
Para solucionar esta desavenencia, lo más interesante suele ser crear una clase personalizada y sobreescribir el método ToString de esta. Aunque si uno quiere ser un poco más genérico, puede utilizar una clase como la siguiente para que la parte no visible (la parte del Value) pueda tomar cualquier tipo de valor (int, long, guid, string, object, …) que deseemos.
using System;
namespace System.Windows.Forms
{
public class UnboundBoxItem
{
#region Members and Properties
private string _display;
public string Display
{
get { return _display; }
set { _display = value; }
}
private TValue _value;
public TValue Value
{
get { return _value; }
set { _value = value; }
}
#endregion
#region C'tors
public UnboundBoxItem()
{
_display = string.Empty;
}
public UnboundBoxItem(string display, TValue value)
{
_display = display;
_value = value;
}
#endregion
#region Functions
public override string ToString()
{
return _display.ToString();
}
public override bool Equals(object obj)
{
if (obj is UnboundBoxItem)
{
UnboundBoxItem ubi = (UnboundBoxItem)obj;
return ubi.Display.Equals(Display) && ubi.Value.Equals(Value);
}
else
return base.Equals(obj);
}
///
/// Hacemos esto para que no genere un Warning.
///
public override int GetHashCode()
{
return base.GetHashCode();
}
#endregion
}
}
Así pues, para rellenar nuestro ComboBox/ListBox lo único que tendríamos que hacer para cada elemento sería algo como:
UnboundBoxItem item = new UnboundBoxItem("Primer elemento", 1);
comboBox.Items.Add(item);
Ahora bien, cada vez que vayamos a recuperar el elemento seleccionado, tendremos que hacer un casting dado que la propiedad SelectedItem devuelve object.
Pues con este sencillo truco, aprovecharemos toda la flexibilidad y potencia que ofrecen tanto los comboBox como los listBox.
