Как я могу получить предыдущее значение ячейки DataGridView с помощью события CellValueChanged?

#c# #datagridview

#c# #datagridview #обработка событий

Вопрос:

Я пишу приложение на C #, которое использует DataGridView, и я хотел бы проверять входные данные каждый раз, когда пользователь изменяет имеющиеся там данные.

Я начал с использования события CellValidating, в котором есть действительно хороший метод CancelEdit(), который вернет ячейке ее предыдущее значение. Однако это событие запускается каждый раз, когда пользователь покидает ячейку, независимо от того, изменилось оно или нет.

Поддерживает ли CellValueChanged какой-либо метод отмены или отката к предыдущему значению? Таким образом, я мог бы по-прежнему проверять данные, но не тратить время на ячейки, которые в этом не нуждались, но предпочел бы не жертвовать возможностью восстановления ячейки, если данные недействительны.

Вот немного кода:

 private void dataGrid1_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
    if(dataGrid1.Columns[e.ColumnIndex].Name == "dateColumn")
    {
        String input = e.FormattedValue.ToString();

        // Split the date from MM/DD/YYYY format
        String[] temps = input.Split('/');
        try
        {
            if(temps[2].Length != 4)
                MessageBox.Show("The year entered is not the correct length.", "Invalid Year", MessageBoxButtons.OK);

            DateTime date = new DateTime(Convert.ToInt32(temps[2]), Convert.ToInt32(temps[0]), Convert.ToInt32(temps[1]));
        }
        catch (Exception ex) // If exception is thrown, date was invalid
        {
            MessageBox.Show("The date entered was invalid.", "Invalid date", MessageBoxButtons.OK);
            dataGrid1.CancelEdit(); // Set cell value back to what it was prior to user's change
            e.Cancel = true; // Have focus stays with this cell rather than move down a row.
        }
    }
}
  

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

1. Пожалуйста, опубликуйте свой код вместо того, чтобы только описывать его.

2. вы могли бы попробовать cellbeginedit и cellendedit

Ответ №1:

Вы могли бы попробовать другой подход, подобный этому:

 private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    newvalue = (int)dataGridView1[e.ColumnIndex, e.RowIndex].Value;
}

private void dataGridView1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
    oldvalue = (int)dataGridView1[e.ColumnIndex, e.RowIndex].Value;
}
  

Предполагая, что это значение int, если это другой тип данных, тогда также будет работать (за исключением, конечно, переменных oldvalue и newvalue, которые также должны быть этого типа).

Или, судя по вашему вопросу, речь идет только о старом значении, тогда вам понадобится только событие CellBeginEdit, а затем использовать переменную oldvalue внутри события проверки.

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

1. Это неплохая идея, я попробую что-нибудь подобное. Я предполагаю, что вы сделали newvalue и oldvalue глобальными, чтобы к ним можно было получить доступ из других обработчиков событий?

2. Я выберу это в качестве ответа, это было действительно полезно и сделало именно то, что я хотел. Однако я узнал, что CellValueChanged вызывается до CellEndEdit (как и CellValidation), поэтому я не могу сравнить старое и новое значение, но я могу сохранить старое значение в BeginEdit и при необходимости восстановить значение ячейки. Другими словами, мне нужен был только CellBeginEdit и либо CellValueChanged, либо CellValidation. Большое спасибо!

Ответ №2:

ИМХО лучшее решение, потому что базовый DataTable не будет помечен как измененный, если вы отклоните значение. Старое значение будет отображено автоматически

 private void dataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    var underlyingDataRow = ((DataRowView)dataGridView.Rows[e.RowIndex].DataBoundItem).Row;
    if (DoesNotMeetYourCondition)
    {
       row.RejectChanges();
    }
  

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

1. Вау, мне это действительно нравится! Позвольте мне попробовать это, когда я буду в офисе в понедельник.

2. RejectChanges() отклонит все изменения, внесенные в строку с момента последнего вызова AcceptChanges(). Таким образом, вы не можете просто напрямую вызвать RejectChanges(), вы должны вызвать AcceptChanges() для условия успеха.

3. Мне нравится аспект привязки к данным, но я был бы разочарован, если бы все изменения в строке были отклонены по ошибке. Я бы предпочел пометить строку datagridview соответствующим сообщением об ошибке.