Почему мой DataGridview отказывается обновляться?

Я обновляю строку в таблице. Подмножество таблицы отображается в DataGridView. Когда я обновляю строку, изменение не отражается в DataGridView. Несмотря на то, что я вызываю DataGridView.Invalidate() и DataGridView.Refresh() после фиксации изменения, мне нужно закрыть приложение, перезапустить и повторно выполнить запрос, прежде чем изменение станет видимым.

Соответствующий код:

private void buttonUpdate_Click(object sender, EventArgs e)
{
    const int TICKETID_COLUMN = 0;

    String _ticketID = dataGridView1.CurrentRow.Cells[SOME_COLUMN].Value.ToString();

    UpdateRecord(_ticketID, textBoxTicketSource.Text,
                textBoxAboutSomeID.Text, textBoxCategoryID.Text, textBoxContactEmail.Text);
}

private void UpdateRecord(string ATicketID, string ATicketSource, string 
    AAboutSomeID, string ACategoryID, string AContactID)
{
    oracleConnection1.Open();
    OracleCommand ocmd = new OracleCommand();
    OracleTransaction ot;
    // Start a local transaction 
    ot = oracleConnection1.BeginTransaction(System.Data.IsolationLevel.ReadCommitted);
    // Assign transaction object for a pending local transaction 
    ocmd.Transaction = ot;
    ocmd.Connection = oracleConnection1;
    try
    {
        ocmd.CommandText = @"UPDATE ABC.CONCERTTICKETS 
                                     SET TICKETSOURCE = :p_TICKETSOURCE, 
                                     ABOUTSOMEID = :p_ABOUTSOMEID, 
                                     CATEGORYID = :p_CATEGORYID, 
                                     CONTACTEMAIL = :p_CONTACTEMAIL 
                                     WHERE TICKETID = :p_TICKETID";
        ocmd.Parameters.Add("p_TICKETSOURCE", ATicketSource);
        ocmd.Parameters.Add("p_ABOUTSOMEID", Convert.ToInt32(AAboutSOMEID));
        ocmd.Parameters.Add("p_CATEGORYID", Convert.ToInt32(ACategoryID));
        ocmd.Parameters.Add("p_CONTACTEMAIL", AContactID);
        ocmd.Parameters.Add("p_TICKETID", ATicketID);
        ocmd.ExecuteNonQuery();
        ot.Commit();

        Popul8TheGrid();

        dataGridView1.Invalidate();
        dataGridView1.Refresh();
    }
    catch (Exception e)
    {
        ot.Rollback();
        throw;
    }
    finally
    {
        oracleConnection1.Close();
    }
}

private void Popul8TheGrid()
{
    int iFromYear = dateTimePickerFrom.Value.Year;
    int iFromMonth = dateTimePickerFrom.Value.Month;
    int iFromDay = dateTimePickerFrom.Value.Day;
    int iToYear = dateTimePickerTo.Value.Year;
    int iToMonth = dateTimePickerTo.Value.Month;
    int iToDay = dateTimePickerTo.Value.Day;

    oracleCommand1.Parameters.Clear();
    oracleCommand1.Parameters.Add("iStartDate", new DateTime(iFromYear, iFromMonth, 
        iFromDay));
    oracleCommand1.Parameters.Add("iEndDate", new DateTime(iToYear, iToMonth, 
        iToDay));
    oracleCommand1.Parameters.Add("iCATEGORYID", 114);
    // OracleRef is apparently like OracleDbType.RefCursor;
    OracleRef or = new OracleRef("_or");
    oracleCommand1.Parameters.Add("cref", or);

    oracleConnection1.Open();

    oracleDataAdapter1.SelectCommand = oracleCommand1;
    oracleDataAdapter1.GetFillParameters();
    oracleDataAdapter1.Fill(oracleDataTable1);
    dataGridView1.DataSource = oracleDataTable1;

    oracleConnection1.Close();
}

Обновлено:

Основываясь на предложении Холла (я пытался ответить комментарием, но он, похоже, завис):

Хорошо, у меня есть это сейчас:

        oracleDataAdapter1.SelectCommand = oracleCommand1;
        oracleDataAdapter1.GetFillParameters();
        oracleDataAdapter1.Fill(oracleDataTable1);
        // I don't see a "Clear" method or some such...
        dataGridView1.DataSource = null;
        //dataGridView1.DataSource = oracleDataTable1;

        BindingSource b = new BindingSource(); 
        b.DataSource = oracleDataTable1; 
        dataGridView1.DataSource = b;
        b.ResetBindings(false);

        oracleConnection1.Close();

... и он по-прежнему работает так же - обновляется, но DataGridView не знает об этом, пока я не перезапущу приложение.


person B. Clay Shannon    schedule 20.03.2012    source источник
comment
Таким образом, вы на самом деле устанавливаете источник данных сетки в нуль, каждый раз создаете новый источник привязки, привязываете источник привязки к toe datagridview, затем сбрасываете привязки, а ваша сетка все еще не отображает новые данные? С вашим кодом происходит что-то очень странное, поскольку шаги, которые у вас есть, на самом деле излишни - вам не нужна половина из них, чтобы это сработало. Что вы видите в таблице данных, если вы пройдете через отладчик? И что произойдет, если вы возьмете источник привязки до переменной уровня класса, а затем просто обновите таблицу данных, а не полностью воссоздаете ее?   -  person David Hall    schedule 21.03.2012


Ответы (3)


Причина, по которой Invalidate() и Refresh() не запрашивают источник данных, заключается в том, что они предназначены для работы только с графической стороной вещей - они оба делают недействительной клиентскую область элемента управления и вызывают перерисовку, но проблема в том, что базовый элемент управления считает, что ничего не изменилось в его источнике данных, поскольку он полагается на источник данных, чтобы сообщить ему, когда это произойдет.

Что вам нужно, так это то, что ваш DataSource будет чем-то, что будет сообщать DataGridView о том, что происходит, например, BindingList<T> или BindingSource, оба из которых имеют событие ListChanged, на которое подписывается DataGridView.

Я думал, что DataTable также информирует сетку об изменении, но я либо ошибся, либо OracleDataTable отличается.

Что должно решить проблему, так это ввести BindingSource и сделать его источником данных для DataGridView. Затем сделайте свой OracleDataTable источником данных источника привязки. Если это не сработает, вы можете вызвать метод ResetBindings() для источника привязки.

BindingSource b = new BindingSource();
b.DataSource = oracleDataTable1;
dataGridView1.DataSource = b;
person David Hall    schedule 20.03.2012

Попробуйте сделать:

dataGridView1.DataSource = null;
dataGridView1.DataSource = oracleDataTable1;
person SamFisher83    schedule 20.03.2012
comment
Пробовал; все еще не обновляется - person B. Clay Shannon; 20.03.2012
comment
Вы делаете это в разделе BeginTransaction? Обычно это работает для меня. Вот аналогичный вопрос: stackoverflow.com/questions/253843/ - person SamFisher83; 20.03.2012

person    schedule
comment
DataGridView не имеет метода DataBind(): «System.Windows.Forms.DataGridView» не содержит определения для «DataBind» и метода расширения «DataBind», принимающего первый аргумент типа «System.Windows.Forms.DataGridView». ' может быть найден (вам не хватает директивы using или ссылки на сборку?) - person B. Clay Shannon; 20.03.2012
comment
DataBind — это метод элемента управления GridView Asp.Net, а не Winforms DataGridView. - person David Hall; 20.03.2012
comment
Вы пробовали .Refresh() или .Update()? - person Leon; 20.03.2012