Here's a little trick that I use all the time. It's simple but handy.
I often find that I want to have a ListBox full of some particular item - to be completely boring, let's say it's a list of Customer objects. We only want to display the customer's name, but it's handy to store the whole Customer object in the ListBox, rather than just the customer's name, because it saves us having to go through the trouble of looking up a Customer based on their name. And of course .NET completely supports this, since you can add any object you want to the ListBox.
If you were to code up a simple implementation of Customer like this one:
public class Customer {
private string name;
private int age;
public Customer(string name, int age) {
this.name = name;
this.age = age;
}
public string Name {
get { return name; }
set { name = value; }
}
public int Age {
get { return age; }
set { age = value; }
}
}
and if you were to then shove a bunch of these into a ListBox, you might be a bit surprised to find the list box displays something like MyNamespace.Customer for every object - hardly what we want.
The reason for this is simple: when confronted with an object, the ListBox displays it by calling ToString on it. And the default implementation of ToString simply returns the name of the type. Not particularly useful in most situations, but what else could they do?
Of course, this is simple to fix if we're the ones that own the Customer object. Simply adding an override of ToString that returns the name would do it. But what if someone else wrote the object and we don't have the source code? Or what if ToString returns something we don't like? I've run into this enough times that I've found the following trick worth including in my standard bag of tricks. I simply write a class that looks like this:
public class ListItemWrapper {
private string text;
private object item;
public ListItemWrapper(string text, object item) {
this.text = text;
this.item = item;
}
public string Text {
get { return text; }
set { text = value; }
}
public object Item {
get { return item; }
set { item = value; }
}
public override string ToString() {
return text;
}
}
Now, when I want to store a Customer in a list, what I do is this instead:
listBox1.Items.Add(new ListItemWrapper(“Craig“, new Customer(“Craig“, 32)));
Which allows me to have any arbitrary text associated with any arbitrary item. Because ToString is overridden to return the text we choose for each object, the ListBox will display what we want it to. And retrieving the item is as simple as casting to ListItemWrapper and then just accessing the Item property.