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

#c# #.net #datagridview #combobox #event-handling

#c# #.net #datagridview #поле со списком #обработка событий

Вопрос:

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

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

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

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

Ответ №1:

Приведенный выше ответ на некоторое время привел меня по пути primrose. Это не работает, поскольку вызывает запуск нескольких событий и просто продолжает добавлять события. Проблема в том, что приведенное выше событие фиксирует 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();
    }
}
  

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

1. Спасибо. Я видел множество примеров использования метода EditedControlShowing, но даже у меня все закончилось сбоем. ПРОБЛЕМА с этим, вероятно, из-за рекурсивных событий.

2. @Severun Hai. Я совсем новичок в C #. Куда я должен поместить события для прослушивания? Я не совсем понимаю эту часть.

3. ребята, обратите внимание, что этот ответ — фактически говорит вам увидеть ответ внизу 🙂 Сэкономьте свое время :))))))

4. Привет, я пробовал этот метод, но он срабатывает несколько раз, когда я изменил только 1 comboboxcell.

5. Как вы на самом деле получаете, какая ячейка является грязной ячейкой? Аргументы события не содержат информации о строке или столбце.

Ответ №2:

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

 var newValue = dataGridView.CurrentCell.EditedFormattedValue;
  

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

1. потрясающий ответ! это спасло меня! в моем случае также потребовалась дополнительная проверка: произошли ли два события при выборе и при переходе к новой ячейке — старое снова вызывает то же событие: но правильное событие легко найти путем проверки. Сфокусированное свойство Combo. Большое спасибо!!!

Ответ №3:

Это код, который запускает событие выбора в выпадающем списке в 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);
}
  

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

1. Это работает, но как сказал @Severun, оно выдает слишком много событий. Некоторое время это работало, но в некоторых случаях это приводит к сбою и вызывает фатальную ошибку типа InvalidOperationException: Operation is not valid because it results in a reentrant call to the SetCurrentAddressCore function . Я использовал решение @Severun, и теперь все работает нормально

2. спасибо за решение @MitjaBonca, но что, если у меня есть два столбца combobox в datagridview.

Ответ №4:

Я реализовал другое решение, которое кажется более отзывчивым (например, быстрее и с меньшим количеством кликов), чем решение Мити Бонка выше. Хотя иногда поле со списком закрывается слишком быстро. При этом используются обратный вызов 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
    }
}
  

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

1. Мне это нравится! спасибо!

Ответ №5:

 ComboBox cmbBox = (ComboBox)sender;                
MessageBox.Show(cmbBox.SelectedValue.ToString());
  

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

1. @Sumett Это может сработать, но в какое событие следует поместить код? Многие обработчики событий изменяют отправителя и EventArgs или то, к чему вы могли бы привести EventArgs. Без контекста, извините, этот ответ довольно бесполезен. Почему бы не предоставить событие …? Без контекста я бы посоветовал никому не тратить время на этот ответ.