ComboBox источник данных: показать полный элемент

#c# #data-binding #combobox #listcontrol

#c# #привязка данных #combobox #listcontrol

Вопрос:

Предположим, у вас есть довольно небольшая последовательность элементов, где каждый элемент имеет свойства: Id и Name.
Id и Name уникальны.
Вы хотите отображать элементы в ListControl как поле со списком.
Вы хотите показать только имя элемента, а не идентификатор.
Когда выбрано имя отображаемого элемента, вы хотите, чтобы идентификатор элемента был выбран в качестве выбранного значения:

Это легко сделать с помощью источника данных, установив свойства DisplayMember и ValueMember

 IList<Item> items = ...
this.ComboBox1.DataSource = items;
this.ComboBox1.DisplayMember = nameof(Item.Name);
this.ComboBox1.ValueMember = nameof(Item.Id)
 

Когда элемент выбран:

 int selectedId = (int) this.ComboBox1.SelectedValue;
 

И вы можете выбрать элемент по идентификатору:

 Item item = ...
this.ComboBox.SelectedValue = item.Id;
 

И вуаля, отображается имя элемента.

Но теперь у меня есть последовательность элементов без свойств, например, перечисление:

 IList<MyEnum> enums = Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>().ToList();
this.comboBox1.DataSource = enums;
 

Этого достаточно, чтобы отобразить перечисления в поле со списком. Нет необходимости устанавливать DisplayMember / ValueMember.
Я могу получить выбранное перечисление:

 MyEnum e = (MyEnum)this.ComboBox1.SelectedValue;
 

Но я не могу его установить:

 MyEnum e = ...
this.ComboBox1.SelectedValue = e;
 

Приводит к исключению: System.Исключение InvalidOperationException: «Невозможно установить SelectedValue в ListControl с пустым значением ValueMember».

Итак, что я должен установить в ValueMember?

Комментарии:

1. Использовать SelectedItem = e

2. Боже, неужели это так просто!

Ответ №1:

CharlieFace предложил следующее решение, и оно сработало:

 private MyEnum SelectedEnum
{
    get => (MyEnum)this.comboBox1.SelectedItem;
    set => this.comboBox1.SelectedItem = value;
}
 

В моем примере со списком, который отображает идентификаторы элементов:

 private Item SelectedItem
{
    get => (Item)this.comboBox1.SelectedItem;
    set => this.comboBox1.SelectedItem = value;
}
 

Таким образом, несмотря на то, что отображается только имя элемента; SelectedItem содержит полный элемент источника данных.

Спасибо, Чарли!