Странное поведение DataTable с DataGridView

Пожалуйста, объясните мне, что происходит. Я создал приложение WinForms .NET, которое имеет DataGridView в форме и должно обновлять базу данных при использовании встроенного редактирования DataGridView.

Форма имеет SqlDataAdapter _da с четырьмя привязанными к ней командами SqlCommand. DataGridView напрямую привязан к DataTable _names.

Такой обработчик CellValueChanged:

private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    _da.Update(_names);
}

не обновляет состояние базы данных, хотя _names DataTable обновляется. Все строки _names имеют RowState == DataRowState.Unchanged

Хорошо, я модифицировал обработчик:

private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    DataRow row = _names.Rows[e.RowIndex];
    row.BeginEdit();
    row.EndEdit();
    _da.Update(_names);
}

этот вариант действительно записывает измененную ячейку в базу данных, но когда я пытаюсь вставить новую строку в сетку, я получаю сообщение об отсутствии строки с индексом e.RowIndex

Итак, я решил доработать обработчик:

private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    if (_names.Rows.Count<e.RowIndex)
    {
        DataRow row = _names.Rows[e.RowIndex];
        row.BeginEdit();
        row.EndEdit();
    }
    else
    {
        DataRow row = _names.NewRow();
        row["NameText"] = dataGridView1["NameText", e.RowIndex].Value;
        _names.Rows.Add(row);
    }
    _da.Update(_names);
}

Когда я вставляю новую строку в сетку, происходят действительно странные вещи: сетка остается такой, какой была до _names.Rows.Add (row); После этой строки в таблицу вставляются ТРИ строки - две строки с одинаковым значением и одна с нулевым значением.

Немного измененный код:

DataRow row = _names.NewRow();
row["NameText"] = "--------------"
_names.Rows.Add(row);

вставляет три строки с тремя разными значениями: одна, как введено в сетку, вторая со значением «--------------» и третья - со значением Null.

Я действительно застрял в догадках, что происходит.


person Paul    schedule 24.11.2012    source источник
comment
Я не уверен, точно ли я продублировал вашу проблему, но у меня есть рабочий пример, где я могу зафиксировать базу данных после изменения значения ячейки, что, как мне кажется, является вашей целью. Разместите код сейчас, прокомментируйте, если он не работает для вас.   -  person David Hall    schedule 25.11.2012


Ответы (3)


У меня есть решение для вас, но позвольте мне объяснить, что происходит. К моменту запуска события CellValueChanged DataGridView обнаружил, что вы внесли изменение в ячейку, и фактически уже поместил значение в таблицу, но таблица все еще находится в режиме редактирования, поэтому RowState измененных строк все еще не изменился. Кроме того, вставленные строки еще даже не отображаются в таблице. Чтобы заставить таблицу отразить эти изменения, вызовите метод EndCurrentEdit () BindingContext формы:

this.BindingContext[_names].EndCurrentEdit();
person Sam Anwar    schedule 24.11.2012
comment
А может лучше использовать другое событие DataGridView? - person Paul; 27.11.2012

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

Значение ячейки изменилось, затем стало:

private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    bs.EndEdit();
    _da.Update(_names);
}
person David Hall    schedule 24.11.2012

ОТВЕТ NECRO: Самый простой способ - использовать другой набор данных только для изменений:

private void UpdateDB()
{
    using (SqlConnection conn = new SqlConnection(SQLString.ConnStr))   // All new connection
    {
        try
        {
            dataAdapter.SelectCommand = new SqlCommand(SQLString.QryStr, conn);
            cmd.DataAdapter = dataAdapter;

            changeSet = dataSet.GetChanges();
            if (changeSet != null)
            {
                dataAdapter.Update(changeSet, "tstRegion");
            }
        }
        catch (Exception e)
        {
            MessageBox.Show(e.ToString());
        }
    }
}

Обратите внимание, что изменения исходного набора данных - это все, что есть в наборе данных изменений.

person JimSnyder    schedule 05.10.2017
comment
К сожалению, я давно не использую .NET, поэтому не могу проверить ваш ответ. - person Paul; 05.10.2017