Thursday, November 22, 2007

Set ComboBox value member

The problem was to have assign and later read the value member of a combo box. Because this can be useful to store the primary key or id of the related object in order to get it fast.

UPDATE: see also my latest post which deals with this issue!

Possible Solution1:
To assign these values a data source is needed which can be a list of any type. To make it simpler and useful I created a class which holds the value to display and the value of the value
public class ComboBoxItem
private string display;
private long value;

public ComboBoxItem(string display, string value)
this.display = display;
this.value = value;

public string Display
set { display = value; }
get { return display; }

public long Value
set { value = value; }
get { return value; }

And here some sample code for the usage of the new class:
ComboBox cb = new ComboBox();
List<ComboBoxItem> items = new List<ComboBoxItem>();
items.Add(new ComboBoxItem("item 1", myObject.ID));
items.Add(new ComboBoxItem("item 2", myObject2.ID));
cb.ValueMember = "Value";
cb.DisplayMember = "Display";
cb.DataSource = items;

Note: I read on a forum that they "complained" that I am not using a generic List; but I am using a generic list, I only forgot to convert the "<" and ">" to be displayed correctly :-)

This line selects the combo box item of myObject2 and shows the appropriate display member:
cb.SelectedValue = myObject2.ID;

This line gets the ID of the selected item:
long selectedItemID = cb.SelectedValue;

And you can retrieve the whole combo box item to do whatever you want:
ComboBoxItem cbi = (ComboBoxItem) cb.SelectedItem;
string selectedItemText = cbi.Display;
long selectedItemID = cbi.Value;

When using the data source property it is not possible to add new items to the combo box with the following code:
cb.Items.Add(new ComboBoxItem("new item", 3);

Possible Solution2:
If you do not want to create a class only for the combobox items you can also use the class "DictionaryEntry" in the namespace System.Collections. This gives you the ability to specify different datatypes for the display and value members as shown in the code below:
this.comboBox1.Items.Add(new DictionaryEntry("integer", 5));
this.comboBox1.Items.Add(new DictionaryEntry("string", "i am a string"));
this.comboBox1.Items.Add(new DictionaryEntry("float", 5.6f));
this.comboBox1.Items.Add(new DictionaryEntry("bool", true));
this.comboBox1.Items.Add(new DictionaryEntry("null", null));
this.comboBox1.Items.Add(new DictionaryEntry(1, 1));

this.comboBox1.DisplayMember = "Key";
this.comboBox1.ValueMember = "Value";

this.comboBox1.DataSource = this.comboBox1.Items;

This code populates a combobox with different DictionaryEntry objects. The key can be any object and the value can also be any object. This adds the flexibility of using different display and value members in the same combobox. The last line is needed in order to get the selected value member through the according property of the combobox; because this is only "enabled" if a datasource is set. To retrieve the selected values you can use code like this:
MessageBox.Show(string.Format("key: {0} - value: {1}", ((DictionaryEntry)this.comboBox1.SelectedItem).Key, this.comboBox1.SelectedValue));

If you have only display - value pairs which have all the same datatypes you could use the generic class KeyValuePair which is in the namespace System.Collections.Generic. With this you could populate your combobox like so:
this.comboBox1.Items.Add(new KeyValuePair("customer 1", 1));
this.comboBox1.Items.Add(new KeyValuePair<string, int>("customer 2", 2));
this.comboBox1.Items.Add(new KeyValuePair<string, int>("customer 3", 3));
this.comboBox1.Items.Add(new KeyValuePair<string, int>("customer 4", 4));

this.comboBox1.DisplayMember = "Key";
this.comboBox1.ValueMember = "Value";

this.comboBox1.DataSource = this.comboBox1.Items;

and obtain the selected item like:
MessageBox.Show(string.Format("key: {0} - value: {1}", ((KeyValuePair<string, int>)this.comboBox1.SelectedItem).Key, this.comboBox1.SelectedValue));

The advantage of this is for sure the type safety; because you do not have to cast the key or the value to the correct datatype. The disadvantage of this is that they have all to be of the same key and value type because otherwise the cast when obtaining the selecteditem would throw an exception.
Hope this may help someone :-)


Anonymous said...
This comment has been removed by a blog administrator.
Anonymous said...

Thanks alot. Finally code that works!


خالد الغامدي said...

thanks but how to set selected value to the object . it's not work !!

Techie Buddha said...

thanks a lots , nice cide and explanation