237

In C# WinApp, how can I add both Text and Value to the items of my ComboBox? I did a search and usually the answers are using "Binding to a source".. but in my case I do not have a binding source ready in my program... How can I do something like this:

combo1.Item[1] = "DisplayText";
combo1.Item[1].Value = "useful Value"
RustyTheBoyRobot
  • 5,891
  • 4
  • 36
  • 55
Bohn
  • 26,091
  • 61
  • 167
  • 254

21 Answers21

415

You must create your own class type and override the ToString() method to return the text you want. Here is a simple example of a class you can use:

public class ComboboxItem
{
    public string Text { get; set; }
    public object Value { get; set; }

    public override string ToString()
    {
        return Text;
    }
}

The following is a simple example of its usage:

private void Test()
{
    ComboboxItem item = new ComboboxItem();
    item.Text = "Item text1";
    item.Value = 12;

    comboBox1.Items.Add(item);

    comboBox1.SelectedIndex = 0;

    MessageBox.Show((comboBox1.SelectedItem as ComboboxItem).Value.ToString());
}
Adam Markowitz
  • 12,919
  • 3
  • 29
  • 21
  • 4
    do we realy need this new class ComboboxItem? i think there is one already exist called ListItem. – Amr Elgarhy Jun 17 '10 at 16:07
  • 19
    I believe that may only be available in ASP.NET and not WinForms. – Adam Markowitz Jun 17 '10 at 16:10
  • yes :( unfortunately it is only in ASP.net ... so what can I do now? – Bohn Jun 17 '10 at 16:13
  • 1
    No. The item is a separate type that is only used for storing the data of the items (text, value, references to other objects, etc). It is not a descendant of a ComboBox and it would be extremely rare that it would be. – Adam Markowitz Jun 17 '10 at 16:30
  • This is either obsolete or wrong. Charles Glisan's and buhtla answers make much more sense now. – Sandman4 Feb 28 '13 at 15:02
  • How is this answer meant to work? Is it that the object added (whatever it is) must have properties named "Text" and "Value" that are reflected by the ComboBox and that is how it knows which one to show? – PandaWood Jun 13 '13 at 06:33
  • `ComboboxItem` seems to be a part of WPF (at least it's contained in `PresentationFramework.dll` according to MSDN). Is there a way to do it a "pure Windows Forms" way? – Azimuth Mar 24 '14 at 07:59
  • 1
    I know I'm somewhat late to the party, but how I did this in a pure windows form environment was to set up a datatable, add items to it, and bind the combobox to the datatable. One would think that there should be a cleaner way of doing it, but I haven't found one (DisplayMember is the property on the combobox you want for text appearing, ValueMember for the Value of the data) – user2366842 Oct 16 '14 at 16:10
  • 1
    Once you have ComboboxItem class, you can add them more easily this way: `comboBox1.Items.Add(new ComboboxItem {Text = "Item text1", Value = 12 });` – Martin Dec 12 '15 at 15:12
  • 5
    how do we get "SelectedValue" or select the item based on value... please reply – Alpha Gabriel V. Timbol May 22 '16 at 01:12
  • Spent hours trying to figure this out.. FYI this only works for ASP.net.. not WinForms – ahinkle Dec 06 '16 at 20:43
211
// Bind combobox to dictionary
Dictionary<string, string>test = new Dictionary<string, string>();
        test.Add("1", "dfdfdf");
        test.Add("2", "dfdfdf");
        test.Add("3", "dfdfdf");
        comboBox1.DataSource = new BindingSource(test, null);
        comboBox1.DisplayMember = "Value";
        comboBox1.ValueMember = "Key";

// Get combobox selection (in handler)
string value = ((KeyValuePair<string, string>)comboBox1.SelectedItem).Value;
fab
  • 2,479
  • 1
  • 16
  • 6
  • 4
    Works perfect and this should be the selected answer. But can't we use comboBox1.SelectedText instead of casting .SelectedItem and take .Value? – Jeffrey Goines Feb 04 '14 at 00:49
  • @fab how do you find item in the combobox with a certain key – Smith Nov 29 '14 at 21:30
  • Is it possible to select an item in the combobox based on the Dictionary Key? like select Key 3 so Item with Key 3 will be selected. – Dror Oct 14 '16 at 11:19
  • This method no longer works for vs2015. Exceptions thrown about not being able to bind to new displaymember and Valuemember – Plater Sep 12 '19 at 15:00
135

You can use anonymous class like this:

comboBox.DisplayMember = "Text";
comboBox.ValueMember = "Value";

comboBox.Items.Add(new { Text = "report A", Value = "reportA" });
comboBox.Items.Add(new { Text = "report B", Value = "reportB" });
comboBox.Items.Add(new { Text = "report C", Value = "reportC" });
comboBox.Items.Add(new { Text = "report D", Value = "reportD" });
comboBox.Items.Add(new { Text = "report E", Value = "reportE" });

UPDATE: Although above code will properly display in combo box, you will not be able to use SelectedValue or SelectedText properties of ComboBox. To be able to use those, bind combo box as below:

comboBox.DisplayMember = "Text";
comboBox.ValueMember = "Value";

var items = new[] { 
    new { Text = "report A", Value = "reportA" }, 
    new { Text = "report B", Value = "reportB" }, 
    new { Text = "report C", Value = "reportC" },
    new { Text = "report D", Value = "reportD" },
    new { Text = "report E", Value = "reportE" }
};

comboBox.DataSource = items;
bluish
  • 26,356
  • 27
  • 122
  • 180
buhtla
  • 2,819
  • 4
  • 25
  • 38
  • 16
    I would like to modify this slightly because a programmer is likely to need a for loop along with this. Instead of an array I used a list `List items = new List();` Then I was able to use the method `items.Add( new { Text = "report A", Value = "reportA" } );` within the loop. – Andrew Feb 25 '15 at 03:09
  • 1
    Andrew, did you get the List to work with the SelectedValue property? – Peter PitLock May 09 '15 at 14:24
  • @Venkat,`comboBox.SelectedItem.GetType().GetProperty("Value").GetValue(comboBox.SelectedItem, null)` – Optavius Dec 08 '16 at 08:46
  • 3
    @Venkat if you use the second solution that sets the `DataSource` you can use the `SelectedValue` or `SelectedText` properties of the combobox, so no need to do any special casting. – JPProgrammer Mar 10 '17 at 05:51
51

You should use dynamic object to resolve combobox item in run-time.

comboBox.DisplayMember = "Text";
comboBox.ValueMember = "Value";

comboBox.Items.Add(new { Text = "Text", Value = "Value" });

(comboBox.SelectedItem as dynamic).Value
Mert Cingoz
  • 732
  • 1
  • 13
  • 12
22

You can use Dictionary Object instead of creating a custom class for adding text and value in a Combobox.

Add keys and values in a Dictionary Object:

Dictionary<string, string> comboSource = new Dictionary<string, string>();
comboSource.Add("1", "Sunday");
comboSource.Add("2", "Monday");

Bind the source Dictionary object to Combobox:

comboBox1.DataSource = new BindingSource(comboSource, null);
comboBox1.DisplayMember = "Value";
comboBox1.ValueMember = "Key";

Retrieve Key and value:

string key = ((KeyValuePair<string,string>)comboBox1.SelectedItem).Key;
string value = ((KeyValuePair<string,string>)comboBox1.SelectedItem).Value;

Full Source : Combobox Text nd Value

Bugs
  • 4,491
  • 9
  • 32
  • 41
cronynaval
  • 221
  • 2
  • 2
16

This is one of the ways that just came to mind:

combo1.Items.Add(new ListItem("Text", "Value"))

And to change text of or value of an item, you can do it like this:

combo1.Items[0].Text = 'new Text';

combo1.Items[0].Value = 'new Value';

There is no class called ListItem in Windows Forms. It only exists in ASP.NET, so you will need to write your own class before using it, the same as @Adam Markowitz did in his answer.

Also check these pages, they may help:

Community
  • 1
  • 1
Amr Elgarhy
  • 66,568
  • 69
  • 184
  • 301
11

Don't know if this will work for the situation given in the original post (never mind the fact that this is two years later), but this example works for me:

Hashtable htImageTypes = new Hashtable();
htImageTypes.Add("JPEG", "*.jpg");
htImageTypes.Add("GIF", "*.gif");
htImageTypes.Add("BMP", "*.bmp");

foreach (DictionaryEntry ImageType in htImageTypes)
{
    cmbImageType.Items.Add(ImageType);
}
cmbImageType.DisplayMember = "key";
cmbImageType.ValueMember = "value";

To read your value back out, you'll have to cast the SelectedItem property to a DictionaryEntry object, and you can then evaluate the Key and Value properties of that. For instance:

DictionaryEntry deImgType = (DictionaryEntry)cmbImageType.SelectedItem;
MessageBox.Show(deImgType.Key + ": " + deImgType.Value);
ChuckG
  • 111
  • 1
  • 2
7
//set 
comboBox1.DisplayMember = "Value"; 
//to add 
comboBox1.Items.Add(new KeyValuePair("2", "This text is displayed")); 
//to access the 'tag' property 
string tag = ((KeyValuePair< string, string >)comboBox1.SelectedItem).Key; 
MessageBox.Show(tag);
Jens Erat
  • 37,523
  • 16
  • 80
  • 96
Ryan
  • 83
  • 1
  • 4
6

If anyone is still interested in this, here is a simple and flexible class for a combobox item with a text and a value of any type (very similar to Adam Markowitz's example):

public class ComboBoxItem<T>
{
    public string Name;
    public T value = default(T);

    public ComboBoxItem(string Name, T value)
    {
        this.Name = Name;
        this.value = value;
    }

    public override string ToString()
    {
        return Name;
    }
}

Using the <T> is better than declaring the value as an object, because with object you'd then have to keep track of the type you used for each item, and cast it in your code to use it properly.

I've been using it on my projects for quite a while now. It is really handy.

Matheus Rocha
  • 1,152
  • 13
  • 22
4

I liked fab's answer but didn't want to use a dictionary for my situation so I substituted a list of tuples.

// set up your data
public static List<Tuple<string, string>> List = new List<Tuple<string, string>>
{
  new Tuple<string, string>("Item1", "Item2")
}

// bind to the combo box
comboBox.DataSource = new BindingSource(List, null);
comboBox.ValueMember = "Item1";
comboBox.DisplayMember = "Item2";

//Get selected value
string value = ((Tuple<string, string>)queryList.SelectedItem).Item1;
Maggie
  • 1,546
  • 16
  • 27
4

Better solution here;

Dictionary<int, string> userListDictionary = new Dictionary<int, string>();
        foreach (var user in users)
        {
            userListDictionary.Add(user.Id,user.Name);
        }

        cmbUser.DataSource = new BindingSource(userListDictionary, null);
        cmbUser.DisplayMember = "Value";
        cmbUser.ValueMember = "Key";

Retreive Data

MessageBox.Show(cmbUser.SelectedValue.ToString());
  • While I was able to fill up the combobox, clicking on it yields this error in VS2019 A QueryInterface call was made requesting the class interface of COM visible managed class 'ComboBoxUiaProvider – MC9000 Mar 15 '20 at 21:20
3

An example using DataTable:

DataTable dtblDataSource = new DataTable();
dtblDataSource.Columns.Add("DisplayMember");
dtblDataSource.Columns.Add("ValueMember");
dtblDataSource.Columns.Add("AdditionalInfo");

dtblDataSource.Rows.Add("Item 1", 1, "something useful 1");
dtblDataSource.Rows.Add("Item 2", 2, "something useful 2");
dtblDataSource.Rows.Add("Item 3", 3, "something useful 3");

combo1.Items.Clear();
combo1.DataSource = dtblDataSource;
combo1.DisplayMember = "DisplayMember";
combo1.ValueMember = "ValueMember";

   //Get additional info
   foreach (DataRowView drv in combo1.Items)
   {
         string strAdditionalInfo = drv["AdditionalInfo"].ToString();
   }

   //Get additional info for selected item
    string strAdditionalInfo = (combo1.SelectedItem as DataRowView)["AdditionalInfo"].ToString();

   //Get selected value
   string strSelectedValue = combo1.SelectedValue.ToString();
Soenhay
  • 3,958
  • 5
  • 34
  • 60
2

Further to Adam Markowitz's answer, here is a general purpose way of (relatively) simply setting the ItemSource values of a combobox to be enums, while showing the 'Description' attribute to the user. (You'd think everyone would want to do this so that it would be a .NET one liner, but it just isn't, and this is the most elegant way I've found).

First, create this simple class for converting any Enum value into a ComboBox item:

public class ComboEnumItem {
    public string Text { get; set; }
    public object Value { get; set; }

    public ComboEnumItem(Enum originalEnum)
    {
        this.Value = originalEnum;
        this.Text = this.ToString();
    }

    public string ToString()
    {
        FieldInfo field = Value.GetType().GetField(Value.ToString());
        DescriptionAttribute attribute = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
        return attribute == null ? Value.ToString() : attribute.Description;
    }
}

Secondly in your OnLoad event handler, you need to set the source of your combo box to be a list of ComboEnumItems based on every Enum in your Enum type. This can be achieved with Linq. Then just set the DisplayMemberPath:

    void OnLoad(object sender, RoutedEventArgs e)
    {
        comboBoxUserReadable.ItemsSource = Enum.GetValues(typeof(EMyEnum))
                        .Cast<EMyEnum>()
                        .Select(v => new ComboEnumItem(v))
                        .ToList();

        comboBoxUserReadable.DisplayMemberPath = "Text";
        comboBoxUserReadable.SelectedValuePath= "Value";
    }

Now the user will select from a list of your user friendly Descriptions, but what they select will be the enum value which you can use in code. To access the user's selection in code, comboBoxUserReadable.SelectedItem will be the ComboEnumItem and comboBoxUserReadable.SelectedValue will be the EMyEnum.

Ali
  • 3,373
  • 5
  • 42
  • 54
2

You may use a generic Type:

public class ComboBoxItem<T>
{
    private string Text { get; set; }
    public T Value { get; set; }

    public override string ToString()
    {
        return Text;
    }

    public ComboBoxItem(string text, T value)
    {
        Text = text;
        Value = value;
    }
}

Example of using a simple int-Type:

private void Fill(ComboBox comboBox)
    {
        comboBox.Items.Clear();
        object[] list =
            {
                new ComboBoxItem<int>("Architekt", 1),
                new ComboBoxItem<int>("Bauträger", 2),
                new ComboBoxItem<int>("Fachbetrieb/Installateur", 3),
                new ComboBoxItem<int>("GC-Haus", 5),
                new ComboBoxItem<int>("Ingenieur-/Planungsbüro", 9),
                new ComboBoxItem<int>("Wowi", 17),
                new ComboBoxItem<int>("Endverbraucher", 19)
            };

        comboBox.Items.AddRange(list);
    }
1

Class creat:

namespace WindowsFormsApplication1
{
    class select
    {
        public string Text { get; set; }
        public string Value { get; set; }
    }
}

Form1 Codes:

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            List<select> sl = new List<select>();
            sl.Add(new select() { Text = "", Value = "" });
            sl.Add(new select() { Text = "AAA", Value = "aa" });
            sl.Add(new select() { Text = "BBB", Value = "bb" });
            comboBox1.DataSource = sl;
            comboBox1.DisplayMember = "Text";
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {

            select sl1 = comboBox1.SelectedItem as select;
            t1.Text = Convert.ToString(sl1.Value);

        }

    }
}
Limitless isa
  • 3,689
  • 36
  • 28
1

You can use this code to insert some items into a combo box with text and value.

C#

private void ComboBox_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
{
    combox.Items.Insert(0, "Copenhagen");
    combox.Items.Insert(1, "Tokyo");
    combox.Items.Insert(2, "Japan");
    combox.Items.Insert(0, "India");   
}

XAML

<ComboBox x:Name="combox" SelectionChanged="ComboBox_SelectionChanged_1"/>
MarredCheese
  • 17,541
  • 8
  • 92
  • 91
1
using (SqlConnection con = new SqlConnection(insertClass.dbPath))
{
    con.Open();
    using (SqlDataAdapter sda = new SqlDataAdapter(
    "SELECT CategoryID, Category FROM Category WHERE Status='Active' ", con))
    {
        //Fill the DataTable with records from Table.
        DataTable dt = new DataTable();
        sda.Fill(dt);
        //Insert the Default Item to DataTable.
        DataRow row = dt.NewRow();
        row[0] = 0;
        row[1] = "(Selecione)";
        dt.Rows.InsertAt(row, 0);
        //Assign DataTable as DataSource.
        cboProductTypeName.DataSource = dt;
        cboProductTypeName.DisplayMember = "Category";
        cboProductTypeName.ValueMember = "CategoryID";
    }
}             
con.Close();
Toni
  • 1,555
  • 4
  • 15
  • 23
FAdao
  • 11
  • 1
0

I had the same problem, what I did was add a new ComboBox with just the value in the same index then the first one, and then when I change the principal combo the index in the second one change at same time, then I take the value of the second combo and use it.

This is the code:

public Form1()
{
    eventos = cliente.GetEventsTypes(usuario);

    foreach (EventNo no in eventos)
    {
        cboEventos.Items.Add(no.eventno.ToString() + "--" +no.description.ToString());
        cboEventos2.Items.Add(no.eventno.ToString());
    }
}

private void lista_SelectedIndexChanged(object sender, EventArgs e)
{
    lista2.Items.Add(lista.SelectedItem.ToString());
}

private void cboEventos_SelectedIndexChanged(object sender, EventArgs e)
{
    cboEventos2.SelectedIndex = cboEventos.SelectedIndex;
}
Chris O
  • 5,017
  • 3
  • 35
  • 42
Miguel
  • 1
0

This is how Visual Studio 2013 does it:

Single item:

comboBox1->Items->AddRange(gcnew cli::array< System::Object^  >(1) { L"Combo Item 1" });

Multiple Items:

comboBox1->Items->AddRange(gcnew cli::array< System::Object^  >(3)
{
    L"Combo Item 1",
    L"Combo Item 2",
    L"Combo Item 3"
});

No need to do class overrides or include anything else. And yes the comboBox1->SelectedItem and comboBox1->SelectedIndex calls still work.

Enigma
  • 1,247
  • 3
  • 20
  • 51
0

This is similar to some of the other answers, but is compact and avoids the conversion to dictionary if you already have a list.

Given a ComboBox "combobox" on a windows form and a class SomeClass with the string type property Name,

List<SomeClass> list = new List<SomeClass>();

combobox.DisplayMember = "Name";
combobox.DataSource = list;

Which means that the SelectedItem is a SomeClass object from list, and each item in combobox will be displayed using its name.

Alex Smith
  • 1,096
  • 8
  • 12
  • True! I have used `DisplayMember` before... I always forget it exists. I got used to the solution I found before I paid attention to this property, also it won't always help. Not all classes have a `Name` or `Tag` property, or have a string property that could be used arbitrarily as a display text. – Matheus Rocha Apr 05 '17 at 01:12
  • This is a good point. If you can modify the class then it might be worth it to add such a property to the class, for example a property 'ComboBoxText' (which could return the ToString() method if available). Alternatively, if the class is not modifiable, it might be possible to create a derived class in which the 'ComboBoxText' property could be implemented. This would only be worth it if you have to add the class to a ComboBox many times. Otherwise, its simpler to just use a dictionary as explained in one of the other answers. – Alex Smith Apr 06 '17 at 02:46
  • Hey Alex, I have made an answer with the ethod I usually use in these cases. I think it's pretty close to what you said or maybe I didn't understand what you said. I didn't derive from the class because some classes might require you to implement methods that we don't want to override (so we'd have a bunch of methods with a simple `base.Method();`), also you'd have to create a derivative class for each different type you wish to add to combo boxes or list boxes. The class I made is flexible, you can use with any type with no extra effort. Look below for my answer, and tell me what you think :) – Matheus Rocha Apr 06 '17 at 03:18
  • I agree, your answer definitely seems more convenient than creating a derived class for each type you want to add to a combobox. Nice job! I think in the future if i don't have a property like 'Name' readily available I'm going to use something like your answer or the dictionary answer :) – Alex Smith Apr 06 '17 at 03:47
0

This is a very simple solution for windows forms if all is needed is the final value as a (string). The items' names will be displayed on the Combo Box and the selected value can be easily compared.

List<string> items = new List<string>();

// populate list with test strings
for (int i = 0; i < 100; i++)
            items.Add(i.ToString());

// set data source
testComboBox.DataSource = items;

and on the event handler get the value (string) of the selected value

string test = testComboBox.SelectedValue.ToString();
Esteban Verbel
  • 738
  • 2
  • 20
  • 39