Не могу получить значение от ComboBox - PullRequest
2 голосов
/ 05 декабря 2009

У меня есть простой comboBox с некоторыми элементами Value / Text. Я использую ComboBox.DisplayMember и ComboBox.ValueMember, чтобы правильно установить значение / текст. Когда я пытаюсь получить значение, он возвращает пустую строку. Вот мой код:

Событие FormLoad:

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

SelectIndexChanged события ComboBox:

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

И он возвращает пустое диалоговое окно. Я также пытался ComboBox.SelectedItem.Value (который VS видит, см. Рисунок), но он не компилируется:

'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

Что я делаю не так?

Ответы [ 6 ]

6 голосов
/ 05 декабря 2009

Не уверен, что означает ComboBox.SelectedValue, у него есть свойство SelectedItem. Это не будет установлено при добавлении элемента, только когда пользователь делает выбор.

Свойство Items является коллекцией System.Object. Это позволяет комбинированному окну хранить и отображать любой тип объекта класса. Но вам придется преобразовать его из объекта в тип вашего класса, чтобы использовать выбранный объект в вашем коде. Это не может работать в вашем случае, вы добавили объект анонимного типа. Вам нужно будет объявить небольшой вспомогательный класс для хранения свойств Value и Text. Пример кода:

  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; }
    }
  }
2 голосов
/ 05 декабря 2009

Как вы видели в отладчике, SelectedItem содержит необходимую вам информацию. Но чтобы получить доступ к SelectedItem.Value, вам нужно привести SelectedItem к соответствующему типу (что проблематично, если вы используете анонимный тип) или использовать отражение. (VS не может скомпилировать SelectedItem.Value, потому что при compile time VS знает только, что SelectedItem имеет тип Object, у которого нет свойства Value.)

Чтобы использовать отражение для получения члена Value, используйте Type.InvokeMember с BindingFlags.GetProperty.

Чтобы привести SelectedItem, объявите именованный тип со свойствами Value и Text вместо использования анонимного типа и добавьте экземпляры именованного типа в ComboBox вместо экземпляров анонимного типа. Затем приведите SelectedItem: ((MyType) (cb.SelectedItem)). Значение.

1 голос
/ 05 декабря 2009

Вы изменяете содержимое ComboBox в обработчике SelectedIndexChanged. Когда вы изменяете содержимое, это приводит к тому, что выбранные элементы сбрасываются. Установите, что вы читаете в ноль, который отображается в окне сообщения в виде пустой строки.

1 голос
/ 05 декабря 2009

Не знаю, почему SelectedValue ничего не возвращает ... Я предполагаю, что это может быть связано с тем, что вы не используете привязку данных (DataSource). Вы должны попытаться присвоить список карт свойству DataSource.

Относительно проблемы с SelectedItem: ComboBox.SelectedItem имеет тип Object, у которого нет свойства с именем Value. Вы должны привести его к типу предмета; но так как это анонимный тип, вы не можете ... вам, вероятно, следует создать тип для хранения значения и текста карточки и привести к этому типу:

Card card = ComboBox.SelectedItem as Card;
if (card != null)
{
    // do something with card.Value
}
0 голосов
/ 08 марта 2013

Чтобы не создавать новый класс для всех ваших комбинированных списков, я бы предложил вам просто использовать KeyValuePair, как в следующем примере:

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

cbPlayer1.DataSource = new List<KeyValuePair<string,string>>()
{new KeyValuePair<string,string>("3","This should have the value of 3")};

Вам все еще нужно разыграть выбранное значение

string selectedValue = (string)cbPlayer1.SelectedValue;

MessageBox.Show(selectedValue);
0 голосов
/ 05 декабря 2009

Мне любопытно, привязываете ли вы комбинированный список к коллекции или заполняете ее вручную. Если вы привязываете комбинированный список к какому-либо источнику данных ... вы должны добавлять элементы в источник данных, а не сам комбинированный список. Когда элемент добавляется в источник данных, выпадающий список должен обновляться в натуральной форме.

Если вы не привязаны, то добавление элемента не приведет к его выбору. Вам нужно будет либо подождать, пока пользователь выберет элемент, либо программно выбрать элемент в коде.

...