#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. Без контекста, извините, этот ответ довольно бесполезен. Почему бы не предоставить событие …? Без контекста я бы посоветовал никому не тратить время на этот ответ.