Выбор первоначально выбранного значения для ComboBox со списком KeyValuePair как DataSource

Я создаю combobox от List от KeyValuePair<int, string>. До сих пор он работал очень хорошо, предлагая пользователю описательное имя, возвращая мне числовой идентификатор.
Однако, что бы я ни пытался, я не могу выбрать первоначально выбранное значение.

public StartUpForm()
{
    InitializeComponent();

    FlowLayoutPanel flowLayout = new FlowLayoutPanel(); //This is necessary to protect the table, which is for some reason collapsing...
    flowLayout.FlowDirection = FlowDirection.TopDown;
    flowLayout.AutoSize = true;
    flowLayout.AutoSizeMode = AutoSizeMode.GrowAndShrink;

    var comboBox = new ComboBox();

    {
        var choices = new List<KeyValuePair<int, string>> ();
        choices.Add(new KeyValuePair<int, string>(1, "hello"));
        choices.Add(new KeyValuePair<int, string>(2, "world"));
        comboBox.DataSource = choices;
        comboBox.ValueMember = "Key";
        comboBox.DisplayMember = "Value";
        flowLayout.Controls.Add(comboBox);
    }
    Controls.Add(flowLayout);

    //None of these work:
    comboBox.SelectedValue = 2;
    comboBox.SelectedValue = 2.ToString();
    comboBox.SelectedValue = new KeyValuePair<int, string>(2, "world");
    comboBox.SelectedValue = "world";
    comboBox.SelectedItem = 2;
    comboBox.SelectedItem = 2.ToString();
    comboBox.SelectedItem = new KeyValuePair<int, string>(2, "world");
    comboBox.SelectedItem = "world";

    return;
}

Результат всегда один и тот же:

введите описание изображения здесь

Как выбрать исходное выбранное значение в ComboBox, используя как DataSource a List<KeyValuePair<int, string>>?

Ответ 1

Связывание не очень хорошо работает внутри конструктора, поэтому попробуйте переместить объявление ComboBox в область формы и попробуйте использовать переопределение OnLoad:

ComboBox comboBox = new ComboBox();

protected override void OnLoad(EventArgs e) {
  comboBox.SelectedValue = 2;
  base.OnLoad(e);
}

Ответ 2

Почему вы используете привязку? Не было бы проще создать класс с int и строковыми свойствами и переопределить ToString(), чтобы показать текст строки:

public class ComboItem
{
    public int Key {get; set;}
    public string Text {get; set;}
    public override string ToString()
    {
        return this.Text;
    }
}

public void OnFormLoad(object Sender, ...)
{
    IEnumerable<ComboItem> comboItems = CreateListComboItems();
    this.ComboBox1.Items.Clear();
    foreach (var comboitem in comboItems)
    {
        this.comboBox1.Items.Add(comboItem);
    }
 }

Подписаться на событие comboBox SelectedIndexChanged:

private void OnComboSelectedIndexChanged(object sender, EventArgs e)
{
    ComboItem selectedItem = (ComboItem)this.comboBox1.SelectedItem;
    ProcessSelectedKey(selectedItem.Key);
}

Добавление: я не могу выбрать первоначально выбранное значение.

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

Хотя свойство ComboBox.Items имеет тип ComboBoxCollection, оно реализует IEnumerable, то есть вы можете использовать Enumerable.Cast() на нем, чтобы передать его в последовательность ComboItems. Используйте Linq, чтобы узнать, есть ли ComboItem с запрошенным ключом и выберите первый найденный ComboItem или выберите или выберите ничего, если ComboItem не содержит этого ключа

// selects the combobox item with key == value
private void SelectComboItem(int value)
{
   this.comboBox1.SelectedItem = 
       this.ComboBox1.Items.Cast<ComboItem>()
           .FirstOrDefault(comboItem => comboItem.Key == value);
}

Код получит коллекцию элементов в поле со списком (который, как мы знаем, является последовательностью ComboItems), поэтому мы можем отображать все элементы в ComboItem. Затем мы пытаемся найти первый ComboItem с ключом, равным значению. Возвращает null, если такого ComboItem нет. Наконец, сделайте это выбранным элементом. Значение null указывает на отсутствие ничего