Sorry if this sounds a bit simple, but using a data grid in Visual Basic.net I'd like to be able to offer the user a chance to update their data once they have done some edits. I do not seem to be able to find an event that fires when this happens! Has anyone accomplished this simple task

DataGrid - user edits
akks
I have a similar kind of problem with my datagrid.
I need to save the changes using a button. If i press the save button after editing keeping the focus on the edited cell(without changes the focus prior to this event) i am getting HasChanges as false.
I tried this code but still it don't work.
Temple
Len Miller
I have an update button, but I wanted it to be disabled if there was nothing to update and enabled as soon as anything changed. Your solution puts me a big step nearer - I can enable the button when they exit the cell. I am left wondering what the TextChanged event of the data grid is supposed to do. It does not fire when the text of a cell changes.
10e
Here's an example form, using data from the Northwind sample database, that demonstrates a simple version of the technique:
Public Class Form4
Inherits System.Windows.Forms.Form
#Region " Windows Form Designer generated code "
Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()
'Add any initialization after the InitializeComponent() call
End Sub
'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents DataGrid1 As System.Windows.Forms.DataGrid
Friend WithEvents SqlDataAdapter1 As System.Data.SqlClient.SqlDataAdapter
Friend WithEvents SqlSelectCommand1 As System.Data.SqlClient.SqlCommand
Friend WithEvents SqlInsertCommand1 As System.Data.SqlClient.SqlCommand
Friend WithEvents SqlUpdateCommand1 As System.Data.SqlClient.SqlCommand
Friend WithEvents SqlDeleteCommand1 As System.Data.SqlClient.SqlCommand
Friend WithEvents SqlConnection1 As System.Data.SqlClient.SqlConnection
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Me.DataGrid1 = New System.Windows.Forms.DataGrid()
Me.SqlDataAdapter1 = New System.Data.SqlClient.SqlDataAdapter()
Me.SqlDeleteCommand1 = New System.Data.SqlClient.SqlCommand()
Me.SqlConnection1 = New System.Data.SqlClient.SqlConnection()
Me.SqlInsertCommand1 = New System.Data.SqlClient.SqlCommand()
Me.SqlSelectCommand1 = New System.Data.SqlClient.SqlCommand()
Me.SqlUpdateCommand1 = New System.Data.SqlClient.SqlCommand()
CType(Me.DataGrid1, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
'
'DataGrid1
'
Me.DataGrid1.Anchor = (((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
Or System.Windows.Forms.AnchorStyles.Left) _
Or System.Windows.Forms.AnchorStyles.Right)
Me.DataGrid1.DataMember = ""
Me.DataGrid1.HeaderForeColor = System.Drawing.SystemColors.ControlText
Me.DataGrid1.Location = New System.Drawing.Point(8, 8)
Me.DataGrid1.Name = "DataGrid1"
Me.DataGrid1.Size = New System.Drawing.Size(272, 256)
Me.DataGrid1.TabIndex = 1
'
'SqlDataAdapter1
'
Me.SqlDataAdapter1.DeleteCommand = Me.SqlDeleteCommand1
Me.SqlDataAdapter1.InsertCommand = Me.SqlInsertCommand1
Me.SqlDataAdapter1.SelectCommand = Me.SqlSelectCommand1
Me.SqlDataAdapter1.TableMappings.AddRange(New System.Data.Common.DataTableMapping() {New System.Data.Common.DataTableMapping("Table", "Customers", New System.Data.Common.DataColumnMapping() {New System.Data.Common.DataColumnMapping("CustomerID", "CustomerID"), New System.Data.Common.DataColumnMapping("ContactName", "ContactName"), New System.Data.Common.DataColumnMapping("ContactTitle", "ContactTitle")})})
Me.SqlDataAdapter1.UpdateCommand = Me.SqlUpdateCommand1
'
'SqlDeleteCommand1
'
Me.SqlDeleteCommand1.CommandText = "DELETE FROM Customers WHERE (CustomerID = @Original_CustomerID) AND (ContactName " & _
"= @Original_ContactName OR @Original_ContactName IS NULL AND ContactName IS NULL" & _
") AND (ContactTitle = @Original_ContactTitle OR @Original_ContactTitle IS NULL A" & _
"ND ContactTitle IS NULL)"
Me.SqlDeleteCommand1.Connection = Me.SqlConnection1
Me.SqlDeleteCommand1.Parameters.Add(New System.Data.SqlClient.SqlParameter("@Original_CustomerID", System.Data.SqlDbType.NVarChar, 5, System.Data.ParameterDirection.Input, False, CType(0, Byte), CType(0, Byte), "CustomerID", System.Data.DataRowVersion.Original, Nothing))
Me.SqlDeleteCommand1.Parameters.Add(New System.Data.SqlClient.SqlParameter("@Original_ContactName", System.Data.SqlDbType.NVarChar, 30, System.Data.ParameterDirection.Input, False, CType(0, Byte), CType(0, Byte), "ContactName", System.Data.DataRowVersion.Original, Nothing))
Me.SqlDeleteCommand1.Parameters.Add(New System.Data.SqlClient.SqlParameter("@Original_ContactTitle", System.Data.SqlDbType.NVarChar, 30, System.Data.ParameterDirection.Input, False, CType(0, Byte), CType(0, Byte), "ContactTitle", System.Data.DataRowVersion.Original, Nothing))
'
'SqlConnection1
'
Me.SqlConnection1.ConnectionString = "data source=.;initial catalog=Northwind;integrated security=SSPI;persist security" & _
" info=False;"
'
'SqlInsertCommand1
'
Me.SqlInsertCommand1.CommandText = "INSERT INTO Customers(CustomerID, ContactName, ContactTitle) VALUES (@CustomerID," & _
" @ContactName, @ContactTitle); SELECT CustomerID, ContactName, ContactTitle FROM" & _
" Customers WHERE (CustomerID = @CustomerID)"
Me.SqlInsertCommand1.Connection = Me.SqlConnection1
Me.SqlInsertCommand1.Parameters.Add(New System.Data.SqlClient.SqlParameter("@CustomerID", System.Data.SqlDbType.NVarChar, 5, "CustomerID"))
Me.SqlInsertCommand1.Parameters.Add(New System.Data.SqlClient.SqlParameter("@ContactName", System.Data.SqlDbType.NVarChar, 30, "ContactName"))
Me.SqlInsertCommand1.Parameters.Add(New System.Data.SqlClient.SqlParameter("@ContactTitle", System.Data.SqlDbType.NVarChar, 30, "ContactTitle"))
'
'SqlSelectCommand1
'
Me.SqlSelectCommand1.CommandText = "SELECT CustomerID, ContactName, ContactTitle FROM Customers"
Me.SqlSelectCommand1.Connection = Me.SqlConnection1
'
'SqlUpdateCommand1
'
Me.SqlUpdateCommand1.CommandText = "UPDATE Customers SET CustomerID = @CustomerID, ContactName = @ContactName, Contac" & _
"tTitle = @ContactTitle WHERE (CustomerID = @Original_CustomerID) AND (ContactNam" & _
"e = @Original_ContactName OR @Original_ContactName IS NULL AND ContactName IS NU" & _
"LL) AND (ContactTitle = @Original_ContactTitle OR @Original_ContactTitle IS NULL" & _
" AND ContactTitle IS NULL); SELECT CustomerID, ContactName, ContactTitle FROM Cu" & _
"stomers WHERE (CustomerID = @CustomerID)"
Me.SqlUpdateCommand1.Connection = Me.SqlConnection1
Me.SqlUpdateCommand1.Parameters.Add(New System.Data.SqlClient.SqlParameter("@CustomerID", System.Data.SqlDbType.NVarChar, 5, "CustomerID"))
Me.SqlUpdateCommand1.Parameters.Add(New System.Data.SqlClient.SqlParameter("@ContactName", System.Data.SqlDbType.NVarChar, 30, "ContactName"))
Me.SqlUpdateCommand1.Parameters.Add(New System.Data.SqlClient.SqlParameter("@ContactTitle", System.Data.SqlDbType.NVarChar, 30, "ContactTitle"))
Me.SqlUpdateCommand1.Parameters.Add(New System.Data.SqlClient.SqlParameter("@Original_CustomerID", System.Data.SqlDbType.NVarChar, 5, System.Data.ParameterDirection.Input, False, CType(0, Byte), CType(0, Byte), "CustomerID", System.Data.DataRowVersion.Original, Nothing))
Me.SqlUpdateCommand1.Parameters.Add(New System.Data.SqlClient.SqlParameter("@Original_ContactName", System.Data.SqlDbType.NVarChar, 30, System.Data.ParameterDirection.Input, False, CType(0, Byte), CType(0, Byte), "ContactName", System.Data.DataRowVersion.Original, Nothing))
Me.SqlUpdateCommand1.Parameters.Add(New System.Data.SqlClient.SqlParameter("@Original_ContactTitle", System.Data.SqlDbType.NVarChar, 30, System.Data.ParameterDirection.Input, False, CType(0, Byte), CType(0, Byte), "ContactTitle", System.Data.DataRowVersion.Original, Nothing))
'
'Form4
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 273)
Me.Controls.AddRange(New System.Windows.Forms.Control() {Me.DataGrid1})
Me.Name = "Form4"
Me.Text = "Form2"
CType(Me.DataGrid1, System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False)
End Sub
#End Region
Private WithEvents cm As CurrencyManager
Private ds As New DataSet()
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
End Sub
Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
SqlDataAdapter1.Fill(ds)
DataGrid1.DataSource = ds
DataGrid1.DataMember = "Customers"
cm = DirectCast(Me.BindingContext(ds, "Customers"), CurrencyManager)
End Sub
Private Sub cm_PositionChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles cm.PositionChanged
If ds.HasChanges Then
If MessageBox.Show("Do you want to save your changes ", "Handle Changes", MessageBoxButtons.YesNo) = DialogResult.Yes Then
SqlDataAdapter1.Update(ds)
cm.EndCurrentEdit()
End If
End If
End Sub
End Class
All things being equal, I have a feeling most users will find this interface pretty irritating. It might be worth considering saving the updates on a button click, or when you close the form. But it's up to you. Also note that this is the simplest possible implementation of the concept, and needs some optmizing for real work.