tags:

views:

977

answers:

5

Hey,

I have a simple comboBox with some Value/Text items in it. I have using ComboBox.DisplayMember and ComboBox.ValueMember to correctly set the value/text. When I try to get the value, it returns an empty string. Here's my code:

FormLoad event:

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

SelectIndexChanged of ComboBox event:

cbPlayer1.Items.Add(new { Value = "3", Text = "This should have a value of 3" });
MessageBox.Show(cbPlayer1.SelectedValue+"");

And it returns an empty dialog box. I also tried ComboBox.SelectedItem.Value (which VS sees, see picture) but it does not compile:

'object' does not contain a definition for 'Value' and no extension method 'Value' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)

alt text

What am I doing wrong?

Thanks

A: 

As you have seen in the debugger, SelectedItem contains the information you need. But to access SelectedItem.Value, you need to cast SelectedItem to the appropriate type (which is problematic if you are using an anonymous type) or use reflection. (VS can't compile SelectedItem.Value because at compile time VS only knows that SelectedItem is of type Object, which doesn't have a Value property.)

To use reflection to get the Value member, use Type.InvokeMember with BindingFlags.GetProperty.

To cast SelectedItem, declare a named type with Value and Text properties instead of using an anonymous type, and add instances of the named type to the ComboBox, instead of instances of the anonymous type. Then cast SelectedItem: ((MyType)(cb.SelectedItem)).Value.

itowlson
+1  A: 

Not sure why SelectedValue doesn't return anything... I assume it could be due to the fact that you're not using data binding (DataSource). You should try to assign a list of cards to the DataSource property.

Regarding the issue with SelectedItem : ComboBox.SelectedItem is of type Object, which doesn't have a property named Value. You need to cast it to the item's type ; but since it is an anonymous type, you can't... you should probably create a type to hold the value and text of the card, and cast to this type :

Card card = ComboBox.SelectedItem as Card;
if (card != null)
{
    // do something with card.Value
}
Thomas Levesque
+1  A: 

You are modifying the contents of the ComboBox in SelectedIndexChanged handler. When you modify the contents, it causes the selected items to be unset. Set you are reading in null, which is displayed in the message box as an empty string.

Mark Byers
+3  A: 

Not sure what ComboBox.SelectedValue means, it has a SelectedItem property. That would not be set when you add an item, only when the user makes a selection.

The Items property is a collection of System.Object. That allows a combo box to store and display any kind of class object. But you'll have to cast it from object to your class type to use the selected object in your code. That can't work in your case, you added an object of an anonymous type. You'll need to declare a small helper class to store the Value and Text properties. Some sample code:

  public partial class Form1 : Form {
    public Form1() {
      InitializeComponent();
      comboBox1.Items.Add(new Item(1, "one"));
      comboBox1.Items.Add(new Item(2, "two"));
      comboBox1.SelectedIndexChanged += new EventHandler(comboBox1_SelectedIndexChanged);
    }
    void comboBox1_SelectedIndexChanged(object sender, EventArgs e) {
      Item item = comboBox1.Items[comboBox1.SelectedIndex] as Item;
      MessageBox.Show(item.Value.ToString());
    }
    private class Item {
      public Item(int value, string text) { Value = value; Text = text; }
      public int Value { get; set; }
      public string Text { get; set; }
      public override string ToString() { return Text; }
    }
  }
Hans Passant
This is the method I prefer to go for. Thanks for the help, it worked.
AlexDemers
A: 

I am curious whether you are binding the combobox to a collection, or populating it manually. If you are binding the combobox to a data source of some kind...you should be adding items to the data source, not the combobox itself. When an item is added to the datasource, the combobox should update in kind.

If you are not binding, then adding an item will not cause that item to be selected. You would need to either wait for the user to select the item, or programmatically select the item in code.

jrista