Какое событие фиксирует изменение значения в поле со списком в DataGridViewCell?

Я хочу обработать событие, когда значение изменяется в ячейке ComboBox в ячейке DataGridView.

Есть событие CellValueChanged, но оно не срабатывает, пока я не щелкну где-нибудь еще внутри DataGridView.

Простой ComboBox SelectedValueChanged срабатывает сразу после выбора нового значения.

Как я могу добавить слушателя в поле со списком, которое находится внутри ячейки?


person yurib    schedule 13.04.2011    source источник


Ответы (5)


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

Последний ответ о CurrentCellDirtyStateChanged — правильный путь. Я надеюсь, что это поможет кому-то не попасть в кроличью нору.

Вот код:

// Add the events to listen for
dataGridView1.CellValueChanged += new DataGridViewCellEventHandler(dataGridView1_CellValueChanged);
dataGridView1.CurrentCellDirtyStateChanged += new EventHandler(dataGridView1_CurrentCellDirtyStateChanged);



// This event handler manually raises the CellValueChanged event 
// by calling the CommitEdit method. 
void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
    if (dataGridView1.IsCurrentCellDirty)
    {
        // This fires the cell value changed handler below
        dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
    }
}

private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    // My combobox column is the second one so I hard coded a 1, flavor to taste
    DataGridViewComboBoxCell cb = (DataGridViewComboBoxCell)dataGridView1.Rows[e.RowIndex].Cells[1];
    if (cb.Value != null)
    {
         // do stuff
         dataGridView1.Invalidate();
    }
}
person Severun    schedule 23.01.2014
comment
Это мне очень помогло, как раз то, что я искал. Спасибо - person jason.kaisersmith; 29.01.2014
comment
Спасибо. Я видел множество примеров использования метода EditedControlShowing, но в итоге я даже привел к сбою .NET из-за, вероятно, рекурсивных событий. - person Jonas; 23.06.2015
comment
@Северун Хай. Я совсем новичок в С#. Где я должен разместить события для прослушивания? Я не совсем понимаю эту часть. - person MRu; 29.06.2016
comment
ребята - обратите внимание, что этот ответ - на самом деле говорит Вам увидеть ответ внизу :) Сэкономьте свое время :)))))) - person Kamornik Cola; 05.10.2017

Вы также можете обработать событие CurrentCellDirtyStateChanged, которое вызывается всякий раз, когда значение изменяется, даже если оно не зафиксировано. Чтобы получить выбранное значение в списке, вы должны сделать что-то вроде:

var newValue = dataGridView.CurrentCell.EditedFormattedValue;
person Meta-Knight    schedule 13.04.2011
comment
потрясающий ответ! это спасло меня! в моем случае также требуется дополнительная проверка: при выборе и при переходе к новой ячейке происходят два события - старое снова вызывает одно и то же событие: но правильное событие легко найти, проверив свойство .Focused Combo. Большое спасибо !!! - person Kamornik Cola; 05.10.2017

Это код, который вызовет событие выбора в comboBox в dataGridView:

public Form1()
{
    InitializeComponent();

    DataGridViewComboBoxColumn cmbcolumn = new DataGridViewComboBoxColumn();
    cmbcolumn.Name = "cmbColumn";
    cmbcolumn.HeaderText = "combobox column";
    cmbcolumn.Items.AddRange(new string[] { "aa", "ac", "aacc" });
    dataGridView1.Columns.Add(cmbcolumn);
    dataGridView1.EditingControlShowing += new DataGridViewEditingControlShowingEventHandler(dataGridView1_EditingControlShowing);
}

private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
    ComboBox combo = e.Control as ComboBox;
    if (combo != null)
    {
        combo.SelectedIndexChanged -= new EventHandler(ComboBox_SelectedIndexChanged);
        combo.SelectedIndexChanged += new EventHandler(ComboBox_SelectedIndexChanged);
    }
}

private void ComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
    ComboBox cb = (ComboBox)sender;
    string item = cb.Text;
    if (item != null)
        MessageBox.Show(item);
}
person Mitja Bonca    schedule 13.04.2011
comment
Это работает, но как сказал @Severun, он вызывает слишком много событий. Некоторое время это работало, но в некоторых случаях выдавало фатальную ошибку типа InvalidOperationException: Operation is not valid because it results in a reentrant call to the SetCurrentAddressCore function. Я использовал решение @Severun, и теперь все работает нормально. - person 56ka; 26.08.2015
comment
спасибо за решение @MitjaBonca, но что, если у меня есть два столбца со списком в datagridview. - person bhavikshah28; 30.06.2016

Я реализовал другое решение, которое кажется более отзывчивым (например, быстрее и меньше кликов), чем Mitja Bonca выше. Хотя иногда выпадающий список закрывается слишком быстро. Это использует обратный вызов CurrentCellDirtyStateChanged и CellMouseDown.

private void myGrid_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
    if (myGrid.CurrentCell is DataGridViewComboBoxCell)
    {
        myGrid.CommitEdit(DataGridViewDataErrorContexts.Commit);
        myGrid.EndEdit();
    }
}

private void myGrid_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
{
    if (myGrid.Rows[e.RowIndex].Cells[e.ColumnIndex] is DataGridViewComboBoxCell)
    {
        myGrid.CurrentCell = myGrid.Rows[e.RowIndex].Cells[e.ColumnIndex];
        myGrid.BeginEdit(true);
        ((ComboBox)myGrid.EditingControl).DroppedDown = true; // Tell combobox to expand
    }
}
person jkulpe    schedule 14.04.2021

person    schedule
comment
@Sumett Это может сработать, но в какое событие следует поместить код? Многие обработчики событий изменяют то, что представляют собой Sender и EventArgs или то, к чему вы можете привести EventArgs. Без контекста, извините, этот ответ довольно бесполезен. Почему бы не предоставить событие...? Без контекста я бы посоветовал никому не тратить время на этот ответ. - person Dano; 10.02.2019