DataGridView detect changes not working as expected - vb.net

I have a program that is going to load data into a DataGridView, where users can edit/add/delete data. When they close out of the form, if there are any changes made, it will ask if the user wants to save the changes to the database.
So I have a DataTable that I load and assign to the DataSource of the DataGridView. I can then make changes to the data within the table, and if I call the DataSet.Update method, it updates.
However, if I call the DataTable.GetChanges method and look to see the changes, I get nothing, unless I have tabbed/clicked/whatever off of the current row of the DataGridView (in which case .GetChanges works) This leads me to believe that the changes are not committing to the DataTable unless the row loses focus.
So, is there a way to check to see if any cell is changed in a DataGridView, or a way to commit those changes without tabbing off of the row?
Again, this fails me if I don't change the row in the GridView, but works otherwise. I want it to work in both situations.
Dim changedRows As New DataTable()
changedRows = dtInfo.GetChanges(DataRowState.Modified Or DataRowState.Added Or DataRowState.Deleted)
If Not changedRows Is Nothing Then
....
End If

You can call the Form.ValidateChildren method, this will validate and commit all controls in the form, including your DataGridView. This method returns false if there is a validation error.

Related

Is there a way to stop myDataSet.HasChanges() returning true if the only change is a new row?

I have a Button on my Form that when clicked calls myBindingSource.AddNew(). Controls relevant to setting the values on that new row then become visible.
On the close event of that Form i call myDataSet.HasChanges() and if it returns True, i prompt the User if they would like to save the changes they have made.
In the situation where the User clicks to add a new row but then closes the Form, (for whatever reason) without setting any values, myDataSet.HasChanges() will return True obviously because there is the adding of a new row.
What i would like is a way to make it return False if the only change is a new row.
I have tried calling myBindingSource.EndEdit() then myDataSet.AcceptChanges immediately after myBindingSource.AddNew() but myDataSet.HasChanges() still returns True.
I thought by calling myDataSet.AcceptChanges() it would essentially wipe the slate clean and only changes made after that point would be picked up.
Or alternatively if there is a better approach to this i would like to hear it.
I am keen on the idea of only saving back to the DataBase in one go when prompting to save, rather than inserting the new row on the Button.Click and updating that row on each value change.
To be more specified than my comment:
If myDataSet.HasChanges(DataRowState.Deleted Or DataRowState.Modified) Then

CurrentRow in Datagridview changed before Validating by RowHeaderClick. Can i stop this?

I have my current validation of the entered data in the DataGridView located in the RowValidating event. This is working fine for every scenario so far, besides the User clicking the Row Header.
In this case the CurrentRow will be set to nothing even before the RowValidating event triggers. Alot of my methods that are triggered in the case of the data validation are using the currentRow to access data from the DataGridView.
Is there a way to fix this issure without changing the usage of currentRow?

Button doesn't work after DataGridView Validating Event

I have a Form with a TabControl on it. On one of the TabPages is a DataGridView with a New- and Delete-Button below it. I also have a Validating-Event for the DataGridView. Inside the Event I do some checking. If the conditions are not met I do a simple:
e.Cancel = True
Return
But after that my Delete-Button isn't working anymore. Even if I set a Breakpoint right at the start of the Click-Event nothing is happening what could that be? I have set the CausesValidation to false on the Button.
Update
I need to handle both Events, because the Sum of this DataGridView is compared to another value. The Sum can't be smaller or bigger than the other Value. But the User can enter what he wants as long as at the End the Sum is correct. I can't do that in the CellValidating because as soon as I change a Value the Sum doesn't match anymore
Update
I have observerd the following Scenarios where it doesn't work:
I change Data in the DataGridView and then trigger the Validating-Event. It starts working again when I input correct Data and switch Tabs
I create a new Row, trigger the CellValidating-Event and after that the DGV Validating-Event

GridView does not update DataTable

I am using a DevExpress XtraGrid/View for windows forms. The datasource of the grid is a binding source, which is connected to a dataset. My problem is, this table adapter does not update the datatable. I can insert new rows without problems, but I can't update. No error message is thrown; when I save changes, the row value just reverts. This happens for every column in the row. Here is my code for saving and then reloading data:
' Class variable
Private _invoiceDetailsAdapter As dsInvoiceDetailsTableAdapters.inv_InvoiceDetailsTableAdapter = New dsInvoiceDetailsTableAdapters.inv_InvoiceDetailsTableAdapter()
'Save Data
InvInvoiceLineBindingSource.EndEdit()
_invoiceDetailsAdapter.Update(DsInvoiceDetails.inv_InvoiceDetails)
'Load
DsInvoiceDetails.inv_InvoiceDetails.Clear()
If Me._invoiceId > 0 Then
_invoiceDetailsAdapter.Fill(DsInvoiceDetails.inv_InvoiceDetails, _invoiceId)
InvInvoiceLineBindingSource.Sort = "LineNum"
End If
I've figured out that it must be the dataset itself, because I've tried using a regular DataGridView with the dataset, to no avail. I generated the dataset through the wizard and had to add ColumnName and SourceColumn properties in the parameters for Insert & Update. The parameters for Insert & Update look identical as far as properties are concerned.
I've also tried creating new datasets, datatables, binding sources and tableadapters. I've even tried a DataAdapter but there was no difference. I have literally spent 2 weeks now looking through the properties and debugging, trying to find a cause.
Can someone please offer some advice?
The problem was DevExpress' XtraGrid functionality.
The XtraGrid does not immediately save an edit value to the linked dataset. The modified row is usually posted to the data object when focus is moved to another grid row. You can programmatically force the update by calling the UpdateCurrentRow method. In your case you should only call the CloseEditor and UpdateCurrentRow methods before updating the dataset via the DB adapter object.
So if a user only updates only one row, those changes go nowhere. Read on for a code snippet...
http://www.devexpress.com/Support/Center/Question/Details/A327

Updating a control on another form with the results of a dialog box

I made a windows form which contains a listbox (named VenueList). The listbox is pulling it's values from a list provided by a binding source VenuesBindingSource which is pulling in a ID for the value and a name for the text.
There is a button which is causing a DialogBox to appear which is asking for values to store in the database for a NEW venue. Once the values are filled and insert the database, what's supposed to happen is that the dialog box closes and goes back to the original form which invoked it.
However, instead of updating the list. The list stays the same. But if you close the form and reopen it, you see that a new value was added.
TournamentSettings.VenuesTableAdapter.InsertVenueQuery(Trim(VenueNameTxt.Text), Trim(VenueAddress1Txt.Text), Trim(VenueAddress2Txt.Text), Trim(VenueCityTxt.Text), Trim(VenueProvinceTxt.Text), Trim(VenueZipTxt.Text), Trim(CountryBox.SelectedValue), Trim(VenuePhoneNo.Text), VenueType.SelectedText, VenueWebAddress)
TournamentSettings.VenuesTableAdapter.Fill(TournamentSettings.VenueNameList.Venues)
In the above code, InsertVenueQuery is the name of a query from the designer which is invoked to add the values onto the tableadapter VenuesTableAdapter which is used to fill the combo box on load. I also sent the Fill command to refill the table with the new value.
So the question is, should I go about doing this another way, rather than feeding the Table adapter and sending a fill command on to the datatable? Or is there something that I'm not doing here which I should to force that value into the list. I'm tempted to redo everything outside of the designer but that's a lot of code since I have to essentially run two commands (one to insert the data, and another to get the ##IDENTITY value since this is run on an access database.)
Okay. This one I had to think about for a moment.
Instead of me creating a block of done on the load event, I instead created a sub function called "FillVenueList".
I used the following block of code:
Public Sub FillVenueList()
' Adding values from database to a datatable.
' From there will add to the list box.
Dim VenueConnection As New OleDb.OleDbConnection(DBconnection)
VenueConnection.Open()
Dim VenueConnectionQuery As New OleDb.OleDbCommand("SELECT VenueID, VenueName FROM Venues", VenueConnection)
Dim VenueDataAdapter As New OleDb.OleDbDataAdapter(VenueConnectionQuery)
Dim VenueDataSet As New DataSet
VenueDataAdapter.Fill(VenueDataSet, "Venues")
TrnVenueLst.DataSource = VenueDataSet.Tables("Venues")
TrnVenueLst.DisplayMember = "VenueName"
TrnVenueLst.ValueMember = "VenueID"
VenueConnection.Close()
End Sub
From there I called THIS sub on both the form AND the Add Venue window and I can safely see that this works. SO THAT is how you get a new value onto the form, don't use it as a part of the Load Event but rather call it from the load event block, then call it when you want to add to the list.