Windows Develop Bookmark and Share   
 index > Windows Forms Data Controls and Databinding > Force DataGridView update
 

Force DataGridView update

In the following scenario the DataGridView is not updating as I would expect.

I've reviewed the online documentation and the FAQ in this forum and haven't been able todetermine what is causing the issue. As I'm a novice at .NET data programming, I imagine there is something I'm missing relative to the intended use of these features.

System configuration:
Visual Studio 2008 version 9.0, Visual Basic 2008 Express SP1, .NET Framework version 3.5 SP1
Running on32 bit Windows XP Professional SP2

Program details:
Single table database via SQL Server 2008 Compact Edition 3.5
The database was created in Visual Studio Database Designer.
The dataset was created using the Visual Studio DataSet Wizard.
The DataSet Wizard generated the associated BindingSource, TableAdapter and TabelAdapterManager.

A DataGridView is used to display table data and allow the user to select records (rows).
Edits are not allowed in the DataGridView.

The DataGridView DataSource is the BindingSource.
The DataGridView DataMember is blank which I believe is correct for a single table dataset.

The BindingSource DataSource is the DataSet.
The BindingSource DataMember is the table.

The DataSet is filled in the Form_Load event as follows -
TableAdapter.Fill(DataSet.Table)

Edits are performed in code via an editable record.
The program creates an editable record as follows -

Dim Record as DataRow

The program creates a new record for editing as follows -

Record = DataSet.Table.NewRow

The program allows editing of existing records as follows -

Record = TableAdapter.GetData(DataGridView.CurrentRow.Index)

The program saves the edited results as follows -

TableAdapter.Update(Record)

Issue:
When a new record is added the edits made by the program show up in the DataGridView as expected.
However, when an existing record is selected edits made by the program do not show up in the DataGridView. When the program is exited and restarted, the edits show up verifying the database was updated.
If the following line is added following the TableAdapter.Update(Record) the updates do show up in the DataGridView.

TableAdapter.Fill(DataSet.Table)

The unwanted side effect is the DataGridView.CurrentRow.Index is reset. Although the Index can be captured it can't be programmatically set since it is a read-only property. It also doesn't seem that a Fill should need to be issued following an Update.

Request:
Please instruct me on the proper use of the .NET data features relative to the above.
Is there a book on ADO.NET forVisual Studio 2008, Visual Basic 2008 Express with.NET Framework version 3.5? I've seen books on ADO.NET 2.0 but am concerned they won't be up to date.

Thanks,
Eric
Eric-67220  Tuesday, August 25, 2009 5:27 PM
Now i got it - The proble is "quite" obvious.

The reason you don't get the update to the grid is the way you (or .NET) retrieve the actual row. For that you reffer to a call on GetData() method of the tableadapter. Pressing F12 on this method reveals the problem. The GetData() actually returns a new dataTable which is populated again but has neither been referenced by the bindingsource nor the grid. So you end up changing data but you will not see it until you refresh the grid by refetching from the db. i didn't deal with automatically generated dataSets very much so i didn't notice in the first place.

To solve this litle issue, simply do the update on the original dataTable as you do in the new record method.
Like:

Private Sub btnUpdate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnUpdate.Click
r = TestDatabase1DataSet.test.Rows(TestDataGridView.CurrentRow.Index)
r("name") &= "+"
TestTableAdapter.Update(r)
End Sub
(Excuse any mistyping as i don't know VB ;-)

Hope it is working now on your side as well.
  • Marked As Answer byEric-67220 Friday, August 28, 2009 2:38 PM
  •  
Christoph Wagner  Friday, August 28, 2009 7:23 AM
If your Update is in the same database session (connection) there is no particular need to refetch the data from the db (via TableAdapter.Fill) - You only need to push the changes made inside you code staments to the front end (the grid) - This ca be achieved by calling the BindingSource.ResetBindings after the changes have been made.

BTW. I don't think ADO in 2.0 is any different from ADO in 3.5- They only did some extensions in other topics.
Christoph Wagner  Wednesday, August 26, 2009 6:02 AM

I've been doing some testing but am getting mixed results.
I have the feeling that I am missing something basic.

Correction:
I did fail to list a statement above related to creating a new record.

Record = DataSet.Table.NewRow

The above is followed by the appropriate assignment statements to initialize column values -

Record(ColumnIndex) = value

The assignment statements are followed by -

DataSet.Table.Rows.Add(Record)

Additional information:
The sequence of events relative to the data from program start is as follows -

TableAdapter.Fill(DataSet.Table)

Since the DataGridView.DataSource is the TableBindingSource and the
TableBindingSource.DataSource is the DataSet and TableBindingSource.DataMember is the Table
the DataGridView at this point is filled with rows of data.

A row is then selected in the DataGridView by clicking it's record selector and the record becomes highlighted.

The editable record is then set to the selected record as follows -

Record = TableAdapter.GetData(DataGridView.CurrentRow.Index)

Appropriate updates are made via assignment statements such as -

Record(ColumnIndex) = value

The updated record is then saved to the database as follows -

TableAdapter.Update(Record)

Following the above statement is where I added -

TableBindingSource.ResetBindings(False)

I chose False as the argument since the schema hasn't changed, just the values.

Results:
When the DataGridView is examined the old data is usually still present.
Rarely, I have seen cases where the updates did appear even when I tried carefully to duplicate the same test sequence.
In every case, the program can be exited, which performs the update routine once more, re-started and the updated values do appear in the DataGrid View for the appropriate row.
(I commented out the update call on program exit and it makes no difference. I even have a way to cause update to be run multiple times and that does not make a difference.)

I'm hoping there is something else you notice missing in my steps.
I've read about the AcceptChanges statement and believe it is handled automatically by the Update statement so I am not using it. I also do not use BeginEdit or EndEdit statements.

Eric

Eric-67220  Wednesday, August 26, 2009 6:23 PM
Are you sure you db gets updated when simply executing the procedure without exiting the program (you can check with a different sql-client) ? If not i think you are missing the BindingSource.EndEdit() befor calling the TableAdapter.Update(). This method is used to end edit mode and set the rowstates of the dataTable accordingly.
AcceptChanges() on the dataTable is not a way to go because this will reset the rowstates to be unchanged, thus will definitly never perform an update on your db.
Christoph Wagner  Thursday, August 27, 2009 5:45 AM
Thanks for hanging in there with me on this.

I inserted -

BindingSource.EndEdit

directly in front of -

TabeAdapter.Update(Record)

I also tried this with and without a subsequent -

BindingSource.ResetBindings(False)

All of this had no impact on the issue.

To check to see if the db is being updated without exiting the program I ran through the update scenario in debug mode as usual without exiting the program. The DataGridView did not show the update as usual. I then ran a second instance of the program by running the .exe file in the debug directory. The DataGridView in this second instance did show the update. I believe this confirms the update is making it to the db and leaves the issue open about the non-updating DataGridView in the first instance.

I'm also now uncomfortable about using the index of the DataGridView to index the GetData method since it now appears the DataGridView can become out of synch with the db. Originally I thought they would always be in synch.

Any other insight into the issue is appreciated.

Eric
Eric-67220  Thursday, August 27, 2009 12:53 PM
I tried to reproduce but did not get the results you described maybe you can have look at my test scenario a check for differences.

http://cid-58343fefc9171875.skydrive.live.com/self.aspx/Public/WindowsFormsApplication1.zip
Christoph Wagner  Thursday, August 27, 2009 1:22 PM

Thanks for taking the time to build the test / demo program.

I see you used C#. Although I haven't yet installed the Express version of C# I have read a bit in the VisualC# 2008 Step by Step book published my MS Press.

I pulled the Form3.cs and Program.cs files into notepad to view the code.

I see the Refresh (btnRefresh_Click)procedure performs the TableAdapter.Fill(DataSet.Table) method which is equivalent to what my program does in the Form1_Load procedure.

I see the New row (button1_Click) procedure performs a new row add by creating a new editable row, r, via the declaration statement defining it as DataSet.Table.NewRow , filling the 'name' and 'description' columns with assignment statements, r("ColumnName") = value, adding the new row to the dataset with DataSet.Table.Rows.Add(r) then updating the db with the modified dataset with TableAdapter.Update(r). This is equivalent to what my program does for adding a new record and this part of the program seems to work fine just as yours does.

I also see code for a Save button click event which updates the whole test table, not just the edited record.However, I do not see a Save button on the form. I also agree that as an analog to the operation of my program this is not necessary as I do not perform a complete table update.

To take your test program one step further to see if the issue I am experiencing can be duplicated I suggest the following if you have time.

1) Move the following line of code from the btnRefresh_Click procedure to the Form3_Load procedure.
this.testTableAdapter.Fill(this.database1DataSet.test);

2) Rename the Refresh button to Update and add code that defines an editableDataRow, fills it with the record selected in the DataGridView, updates a field in the editable record then updates the db with the edited record. This might be something as follows -

private void btnRefresh_Click(object sender, EventArgs e)
{
DataRow r = testTableAdapter.GetData(testDataGridView.CurrentRow.Index);
r["name"] &= "+";
this.testTableAdapter.Update(r);
}

3) Run the program. The DataGridView should be filled with the current data from the test table.
Select a record in the DataGridView.
Click the Update button.
If the 'name' column of the selected record updates by appending a "+" character it is working as I have expected but not yet experienced.

I will try to duplicate the same in VB.

Eric

Eric-67220  Thursday, August 27, 2009 4:13 PM
I completed the VB version test program.
It has the same issue.

In order for the DataSet Wizard to build an Update command the dataset must have a Key field.

In my first attempt I built the db with two nvarchar fields named name and description as you have. I then used the DataSet Wizard to build the DataSet.
The New rowbutton procedureworked fine. The testTableAdapter.Update(r) statement made use of the TableAdapter Insert Command. The Insert command needs no key to locate an existing record to operate upon.
However, the Update button procedure failed at the testTableAdapter.Update(r) statement because there was no Update Command in the TableAdapter.

I then updated the db by adding a third field called ID as integer and made it the primary key.
I added the ID field to the DataSet and configured it as an AutoIncrement field. I ran back through the DataSet Wizard so it would build the Delete and Update commands now that there was a primary key.

This now shows the issue I've been dealing with.

I don't have an archive utility (WinZip) to create an archive of the finished program to post as you did.

Below is the VB code and the SQL that was generated in the Table Adapter.

Public Class Form1
    Dim r As DataRow

    'The DataSet configuration Wizard automatically generates
    ' a BindingNavigator ToolStrip for the associated table.
    'I deleted the tool strip from the Designer.
    'I left the generated code for reference and commented it out.
    '--------------
    'Private Sub TestBindingNavigatorSaveItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
    '    Me.Validate()
    '    Me.TestBindingSource.EndEdit()
    '    Me.TableAdapterManager.UpdateAll(Me.TestDatabase1DataSet)

    'End Sub
    '--------------

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'TODO: This line of code loads data into the 'TestDatabase1DataSet.test' table. You can move, or remove it, as needed.
        Me.TestTableAdapter.Fill(Me.TestDatabase1DataSet.test)

    End Sub

    Private Sub btnNew_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNew.Click
        r = TestDatabase1DataSet.test.NewRow
        r("name") = "???"
        r("description") = String.Format("Person {0}", TestDatabase1DataSet.test.Rows.Count)
        TestDatabase1DataSet.test.Rows.Add(r)
        TestTableAdapter.Update(r)
    End Sub

    Private Sub btnUpdate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnUpdate.Click
        r = TestTableAdapter.GetData(TestDataGridView.CurrentRow.Index)
        r("name") &= "+"
        TestTableAdapter.Update(r)
    End Sub
End Class<br/><br/><br/>
TableAdapter UpdateCommand CommandText

UPDATE test
SET       name = @p1, description = @p2, ID = @p3
WHERE (ID = @p4)
Any additional thoughts?
Eric
Eric-67220  Thursday, August 27, 2009 8:28 PM
Now i got it - The proble is "quite" obvious.

The reason you don't get the update to the grid is the way you (or .NET) retrieve the actual row. For that you reffer to a call on GetData() method of the tableadapter. Pressing F12 on this method reveals the problem. The GetData() actually returns a new dataTable which is populated again but has neither been referenced by the bindingsource nor the grid. So you end up changing data but you will not see it until you refresh the grid by refetching from the db. i didn't deal with automatically generated dataSets very much so i didn't notice in the first place.

To solve this litle issue, simply do the update on the original dataTable as you do in the new record method.
Like:

Private Sub btnUpdate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnUpdate.Click
r = TestDatabase1DataSet.test.Rows(TestDataGridView.CurrentRow.Index)
r("name") &= "+"
TestTableAdapter.Update(r)
End Sub
(Excuse any mistyping as i don't know VB ;-)

Hope it is working now on your side as well.
  • Marked As Answer byEric-67220 Friday, August 28, 2009 2:38 PM
  •  
Christoph Wagner  Friday, August 28, 2009 7:23 AM
Thank you very much Christoph.

Your solution works in the test program and the project I'm working on.

I figured it would be a novice type error.

Nice eye opener on F12 to bring up object browser.
I've not seen that before and it looks very handy.
My method of discovery was to look through all the intili-sense tips or use search in help on keywords.

All the best.
Eric

p.s.
I ordered the following book.

Murach's ADO.NET 3.5, LINQ, and the Entity Framework with VB 2008

Eric
  • Edited byEric-67220 Friday, August 28, 2009 2:39 PMMore info.
  •  
Eric-67220  Friday, August 28, 2009 2:38 PM

You can use google to search for other answers

Custom Search

More Threads

• VS 2005 (no beta). DataGridView. Problems with RowHeadersWidth and .ErrorText
• Deployment - reading inputs into file system
• Validating a bound combobox, type error.
• Can a binding source have no current item?
• DataGridView standard practice?
• Query results without display
• Hummph! Table Data Reverts to Previous...
• DataGridView ComboBoxcolumn binding to System.String[]
• binding pivot chart to sql database
• Bunch of Questions