69

I'm using .NET 2.0 and I'm trying to bind a combobox's Datasource to a sorted dictionary.

So the error I'm getting is "DataMember property 'Key' cannot be found on the Datasource".

        SortedDictionary<string, int> userCache = UserCache.getSortedUserValueCache();
        userListComboBox.DataSource = new BindingSource(userCache, "Key"); //This line is causing the error
        userListComboBox.DisplayMember = "Key";
        userListComboBox.ValueMember = "Value";
user803952
  • 854
  • 1
  • 7
  • 8

9 Answers9

143
SortedDictionary<string, int> userCache = new SortedDictionary<string, int>
{
  {"a", 1},
  {"b", 2},
  {"c", 3}
};
comboBox1.DataSource = new BindingSource(userCache, null);
comboBox1.DisplayMember = "Key";
comboBox1.ValueMember = "Value";

But why are you setting the ValueMember to "Value", shouldn't it be bound to "Key" (and DisplayMember to "Value" as well)?

Sorin Comanescu
  • 4,581
  • 2
  • 26
  • 36
  • Well it shouldn't matter either way. But it might make more sense to switch the two around. However the problem I'm having is with "comboBox1.DataSource = new BindingSource(userCache, null);" I can't pull null there because it gives me an error. – user803952 Jun 20 '11 at 14:42
  • 1
    "ArgumentException: Cannot bind to the new display member. Parameter name: newDisplayMember." I don't know what error user803952 got, but this is the error *I* got when I tried doing this with an `IDictionary`. – Ryan Lundy Oct 23 '11 at 04:02
  • This answer worked for me when I tried to bind a Dictionary to a combobox and received the exception "Complex DataBinding accepts as a data source either an IList or an IListSource." – kad81 May 31 '13 at 04:51
  • I had no problem using comboBox1.DataSource = new BindingSource(userCache, null); if you think that it is the offending statement, you can try replacing it with : comboBox1.DataSource = userCache.Select(kv => new { Key = kv.Key, Value = kv.Value }).ToArray(); – dmihailescu Jan 07 '15 at 20:06
  • 3
    another thing you might want to try is to move the line comboBox1.DataSource = new BindingSource(userCache, null); down after you set the DisplayMember and ValueMember – dmihailescu Jan 07 '15 at 21:01
  • @SorinComanescu please I just want to know and wish you update your answer of how can we read data back from database to `combobox` that is use dictionary – sam Sep 24 '18 at 19:56
  • 2
    Sometimes, if DataSource were assigned before DisplayMember did, execution blocks at DisplayMember assignment line. To me, this works -- cBox.DataSource = null; cBox.DisplayMember = "Value"; cBox.ValueMember = "Key"; cBox.DataSource = new BindingSource(dict, null); // @dmihailescu is right – Park JongBum Aug 12 '19 at 00:45
23

I used Sorin Comanescu's solution, but hit a problem when trying to get the selected value. My combobox was a toolstrip combobox. I used the "combobox" property, which exposes a normal combobox.

I had a

 Dictionary<Control, string> controls = new Dictionary<Control, string>();

Binding code (Sorin Comanescu's solution - worked like a charm):

 controls.Add(pictureBox1, "Image");
 controls.Add(dgvText, "Text");
 cbFocusedControl.ComboBox.DataSource = new BindingSource(controls, null);
 cbFocusedControl.ComboBox.ValueMember = "Key";
 cbFocusedControl.ComboBox.DisplayMember = "Value";

The problem was that when I tried to get the selected value, I didn't realize how to retrieve it. After several attempts I got this:

 var control = ((KeyValuePair<Control, string>) cbFocusedControl.ComboBox.SelectedItem).Key

Hope it helps someone else!

CristisS
  • 1,006
  • 1
  • 10
  • 26
  • This works, i have used the following in my own code to get it to work. https://gist.github.com/psykzz/5374823 – PsyKzz Apr 12 '13 at 20:20
  • You can also do it like this (getting the selected value): var value = comboBox.SelectedItem; var someItem = value.GetType().GetProperty("Key").GetValue(value, null); – Miroslav Lazovich Jan 14 '14 at 00:10
  • 1
    The last line could also be reduced to: var control = ((KeyValuePair) cbFocusedControl.ComboBox.SelectedItem).Key; 1) unnecessary outer parentheses, 2) the compiler knows the Key is a Control already because it is casting to KeyValuePair, so the cast to Control is not needed. – Adam Marshall Jun 04 '14 at 14:32
  • @AdamMarshall Thanks for the suggestion. Edited the answer per it. – CristisS Jun 06 '14 at 06:39
  • Instead of all that, why couldn't you just use `cbFocusedControl.ComboBox.SelectedText` and `cbFocusedControl.ComboBox.SelectedValue` to get the DisplayMember and ValueMember respectively? – Sunny Patel Feb 21 '20 at 22:12
6
        var colors = new Dictionary < string, string > ();
        colors["10"] = "Red";

Binding to Combobox

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

Full Source...Dictionary as a Combobox Datasource

Jeryy

jeryymanly
  • 61
  • 1
  • 1
5
userListComboBox.DataSource = userCache.ToList();
userListComboBox.DisplayMember = "Key";
Yelnar
  • 81
  • 1
  • 4
2

A dictionary cannot be directly used as a data source, you should do more.

SortedDictionary<string, int> userCache =  UserCache.getSortedUserValueCache();
KeyValuePair<string, int> [] ar= new KeyValuePair<string,int>[userCache.Count];
userCache.CopyTo(ar, 0);
comboBox1.DataSource = ar; new BindingSource(ar, "Key"); //This line is causing the error
comboBox1.DisplayMember = "Value";
comboBox1.ValueMember = "Key";
Gilles 'SO- stop being evil'
  • 92,660
  • 35
  • 189
  • 229
DeveloperX
  • 4,422
  • 14
  • 22
1

I know this is a pretty old topic, but I also had a same problem.

My solution:

how we fill the combobox:

foreach (KeyValuePair<int, string> item in listRegion)
{
    combo.Items.Add(item.Value);
    combo.ValueMember = item.Value.ToString();
    combo.DisplayMember = item.Key.ToString();
    combo.SelectedIndex = 0;
}

and that's how we get inside:

 MessageBox.Show(combo_region.DisplayMember.ToString());

I hope it help someone

Arman Ebrahimpour
  • 3,537
  • 1
  • 9
  • 37
jacek
  • 19
  • 5
0

Use -->

comboBox1.DataSource = colors.ToList();

Unless the dictionary is converted to list, combo-box can't recognize its members.

th1rdey3
  • 3,888
  • 7
  • 24
  • 61
Swaraj
  • 1
0

Just Try to do like this....

SortedDictionary<string, int> userCache = UserCache.getSortedUserValueCache();

    // Add this code
    if(userCache != null)
    {
        userListComboBox.DataSource = new BindingSource(userCache, null); // Key => null
        userListComboBox.DisplayMember = "Key";
        userListComboBox.ValueMember = "Value";
    }
0

If this doesn't work why not simply do a foreach loop over the dictionary adding all the items to the combobox?

foreach(var item in userCache)
{
    userListComboBox.Items.Add(new ListItem(item.Key, item.Value));
}
thekip
  • 3,536
  • 2
  • 18
  • 39
  • Binding and adding items is not the same thing. Well, maybe that's what the OP really needs, who knows? ;) – jv42 Jun 20 '11 at 14:30
  • I know but I don't see any code that is dependent on the databinding itself. – thekip Jun 20 '11 at 14:31
  • Well what you suggested would work, but the "new ListItem" exists in the System.Web.UI.WebControls Namespace and I wouldn't import that for a windows form application. – user803952 Jun 20 '11 at 14:38
  • I wouldn't do that either, I assume there's a winforms equivalent though? I'm not that into winforms. – thekip Jun 20 '11 at 15:32
  • new ComboBoxItem("itemtext","itemid"); can be used instead – ashveli Oct 15 '19 at 04:41