Публикации
Публикации  »  C#, C++

Получить индекс Combobox-а в ячейке DataGridView

В заметке рассказано как получить индекс выпадающего списка находящегося в ячейке DataGridView, иначе говоря, показано как получить SelectedIndex находящегося в ячейке ComboBox-а. Как добавить в DataGridView колонку с выпадающими списками или с чекбоксами можете посмотреть в одной из прошлых статей.

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

DataGridViewComboBoxCell cmb = dataGridView1.CurrentCell as DataGridViewComboBoxCell;
int i = cmb.SelectedIndex;

Всё потому, что у DataGridViewComboBoxCell нет свойства SelectedIndex. Для решения проблемы я взял за основу информацию из ответа на вопрос на Stack Overflow. Там описано 2 способа как получить индекс выбранного элемента. Первый способ навел меня на размышления и я его реализовал по-своему.

1-й способ. Использование EditingControlShowing

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

Предположим, что у нас в DataGridView вторая колонка содержит ComboBox-ы:

private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
    if (dataGridView1.CurrentCell.ColumnIndex == 1)
    {
        ComboBox combo = e.Control as ComboBox;
        combo.SelectedIndexChanged -= new EventHandler(Control_Changed);
        combo.SelectedIndexChanged += new EventHandler(Control_Changed);
    }
}

Как видно в коде, я сначала "снимаю" с ComboBox-а событие, а потом заново его "навешиваю". Это сделано специально, чтобы не происходило повторных "навешиваний". Пользователь ведь может зайти в ячейку, поменять значение выпадающего списка, потом уйти в другую ячейку, а затем снова вернуться и опять поменять значение списка. Так вот, чтобы каждый раз, когда он редактирует ComboBox не происходило многократного назначения события, я и делаю сначала его удаление.

Теперь обработчик события изменения ComboBox-а:

private void Control_Changed(object sender, System.EventArgs e)
{
    int col = dataGridView1.CurrentCell.ColumnIndex;
    if (col == 1)
    {
        int i = ((ComboBox)sender).SelectedIndex;
        dataGridView1.CurrentRow.Cells[col - 1].Tag = i.ToString();
    }
}

Таким образом, при изменении выбранного элемента в ComboBox-е его индекс запишется в свойство Tag ячейки в которой находится этот ComboBox. Можно так же сохранить выбранный индекс и в массив или куда пожелаете, а потом, когда понадобится индекс, его будет легко получить.

2-й способ. Поиск по значению.

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

DataGridViewComboBoxCell cmb = (DataGridViewComboBoxCell)dataGridView1.CurrentCell;
int i = cmb.Items.IndexOf(cmb.Value);

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

Категория: C#, C++

Комментарии к статье:

Пока комментариев нет, ваш будет первым ;)

Добавить комментарий: