getchanges doesn't return the changes half the time - vb.net

I'm using an Xceed grid bound with a DataSet/DataTable. The thing is, I need to know if changes were made before loading new datas in the grid and therefore, losing changes if I don't save them then.
But neither the DataSet nor DataTable's function getChanges([DataRowState])
return the right thing :S
I've found that sometimes dataColumnChangeEvent is called, but NOT dataRowChangeEvent, these are the times where the changes are not saved into the getChanges() function.
This happens when I click out of the grid while in an editing cell instead of selecting an other of the grid's cell by any way.
Also, I've looked and the rowState is to Unchanged, even if the data do is changed :S
Any ideas?

Great! I've finnaly found a solution.
Even if the dataRowChangeEvent doesn't seem to be called (I'll explain latter)
If the only code in the rowChangeEvent is the code below it works :
Private Sub RowChanged(ByVal sender As Object, ByVal e As DataColumnChangeEventArgs)
If e.Row.RowState = DataRowState.Unchanged Then
e.Row.AcceptChanges()
e.Row.SetModified()
End If
End Sub
We check the rowState because we can only setModified() a row wit the Unchanged state.
We do AcceptChanges() because doing only setModified() removes the changes on the edited cell.
We do SetModified(0 because if not AcceptChanges() leaves the RowState to Unchanged and therefor it doesn't get in the table's getChanges.
EDIT : This brings an other problem, the dataAdapter uses the datarow's original and current Value to do update, delete and insert,
doing "acceptChanges" set OriginalValue to the current Value so delete and Update doesn't work anymore :(
--More--
When I said it doesn't seem to get in the event, it's because the code below :
Private Sub RowChanged(ByVal sender As Object, ByVal e As DataColumnChangeEventArgs)
If e.Row.RowState = DataRowState.Unchanged Then
e.Row.AcceptChanges()
e.Row.SetModified()
End If
MessageBox.Show("hasError=" & IIf(e.Row.HasErrors, "true ", "false ") & _
"; action=" & e.ProposedValue)
End Sub
neither Shows the message Box nor get the changes in the dataTable's getChanges()...
Also, having only
MessageBox.Show("Changing")
instead of the previons messageBox, Do show the messageBox, and Do get the changes right, BUT it then kindof breaks the event so it doesn't go further in the newProjectSelected => no new project is loaded, but it only needs a "re-clic".
So, I've explained how it behaves.
But it's soo strange, I'de appreciate if someone would explaine shuch behaviour.

Related

VB.NET Check for keydown on dragdrop

I've tried searching quite a bit for this answer but haven't been able to find a good solution.
I have a datagridview on my form where users can drag and drop files onto the grid and certain columns are filled in. This works fine.
I want to be able to check if a user has a certain key pressed at the time the file is dropped. If so, I want to use that to add specific data to one of the columns in the datagrid.
Is this possible?
EDIT:
I have used keydown outside of dragdrop before but it seems that I'm missing something. The code I have is below. No matter what I do, I never get "T is pressed" but I always get "T is not pressed".
Private Sub frmReader_DragDrop(sender As Object, e As DragEventArgs) Handles Me.DragDrop
Dim files As String() = CType(e.Data.GetData(DataFormats.FileDrop), String())
If Keyboard.IsKeyDown(Keys.T) Then
MsgBox("T is pressed.")
' Put certain info into the datagridview
Else
MsgBox("T is not pressed.")
' Put other data into the datagridview
End If
End Sub
God, embarassing... I changed "Keys.T" to "Key.T" and it's working fine. Sorry for the bother.

How can cancelling DataGridViewCellValidatingEventArgs replace all event handlers with itself?

I'm having a very strange problem in a VB application. I have a function written like this:
In the innermost condition, two statements are commented out here. These were found to have no effect on the strange behaviour. This is the minimal example I've found causing trouble.
(Note that the names of objects have been changed in this example.)
Private Sub MyForm_CellValidating(ByVal sender As Object, ByVal e As DataGridViewCellValidatingEventArgs) Handles myDGV.CellValidating
Dim dgv As DataGridView = CType(sender, DataGridView)
Select Case dgv.Columns(e.ColumnIndex).Name
Case "uniqueColumn"
' Validate that the values in our unique column are unique.
For i As Integer = 0 To dgv.RowCount - 1
If i <> e.RowIndex Then
' Here i != j, so compare to the value...
If e.FormattedValue = dgv.Rows(i).Cells(e.ColumnIndex).FormattedValue Then
e.Cancel = True
'dgv.ShowRowErrors = True
'dgv.Rows(e.RowIndex).ErrorText = "Data in the unique column must be unique"
End If
End If
Next 'i
Case Else
' Perform no validation.
End Select
End Sub
What trouble, you ask? For some inexplicable reason, whenever the line
e.Cancel = True
is executed, afterwards, nearly all buttons and form widgets in the entire application, including even the close button in its window bar (what a user would use to exit the application) stop doing whatever they previously did and now call this event handler instead.
In other words, commenting out that line (and doing the validation manually when the form is submitted) fixes the problems. I'd like to know why this happens, though. Some pointers:
Here's a list of which things are not affected:
The minimize and maximize button in the top bar.
All objects in its menu bar.
This handler is private to its form class, it's not referenced anywhere else in the application.
I'm at a loss. Just how? What could possibly cause this?
e.Cancel is for stopping the validation when the input is deemed incorrect. This causes the cell to still have focus as the user is expected to correct whatever they did wrong. The CellValidating event will then be raised again whenever the cell is about to lose focus until your code deems the input to be correct.
You can use the Control.CausesValidation property to control whether a control (for instance a button) should raise validation events when it gains focus.

How to get certain column value from selected row to apply to filter?

I'm a complete beginner in VB.NET
I have a task to make a form on visual studio and part of it is to make a functional button for report on orders. On navgrid portion of the form I have master object orders list with order id and order date while in datagridview a child object orderslist with details about the order
I need a button that would give me a report on selected order.
I have made a report already and the code for button so far looks like this:
Private Sub BarButtonItem1_ItemClick_1(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarButtonItem1.ItemClick
CR3.OpenReport("arpt_Sales_Orders", "FilterHere")
End Sub
if the FilterHere part is left empty, i get report on ALL the orders with their details.
I have been trying to look for how to filter out what i need but with little success.
I have also tried to look into how to get value from order list (navgrid on the right) but I'm starting to think this is not gonna bring any use. Nevertheless here are my attempts at this so far
Dim vOrderID = atbv_Sales_Orders.CurrentRow(colOrderID)
Dim data As Object = NavGridView.SelectedRow(colOrderID);
Help would be appreciated. I've been on this for hours with little success
EDIT:
To my understanding i need to add to filter section
OrderID = (OrderID value from selected order)
So the question probably stands as, how do i get that value?
Ok, I have finally found the answer myself. Posting it if someone would come across similiar issue.
First row sets event to fire on pressing the button. Next two are what i needed
Private Sub BarButtonItem1_ItemClick_1(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarButtonItem1.ItemClick
Dim vOrderID As Integer = CInt(cOrderID.Text)
CR3.OpenReport("arpt_Sales_Orders", "OrderID = '" & vOrderID & "'")
End Sub
Works flawlessly for me

search for the same cell in a different DataGridView

I have a section of code that loops through a second DataGridView, trying to match the same index number from the main DataGridVew that the user interacts with:
Private Sub AllegationsDataGridView_CellEnter(sender As Object, e As EventArgs) Handles AllegationsDataGridView.CellEnter
Try
Dim currentcolumn As DataGridViewColumn =
AllegationsDataGridView.Columns(AllegationsDataGridView.CurrentCell.ColumnIndex)
For Each row As DataGridViewRow In parentgrid.Rows
If row.Cells.Item(0).Value = AllegationsDataGridView.CurrentRow.Cells(0).Value Then
parentgrid.CurrentCell = parentgrid(0, row.Index)
End If
Next
Catch ex As Exception
Debug.Print(ex.Message)
End Try
endsub:
End Sub
The problem is is that the datasource could potentially be thousands and thousands of entries, and I don't want this to loop through everysingle row until it finds the match. I wondered if there was a quicker way to approach this? The only examples I have seen when searching all use either a For Each Row approach, or a Loop Until approach, which would still present the same issue.
I suggest you to build a dictionary, when you initialize your datagridview with your datasource, that makes correspond the row key (AllegationsDataGridView.CurrentRow.Cells(0).Value) with the row index in the parentGrid. Use the datasource, and not the datagrid, to build this dictionary.
You will be able to access fastly to the corresponding row.
From comments: They both use the same datasource
I am not sure why a DGV the user doesnt interact with needs to have the CurrentCell kept in synch because if they are bound to the same datasource, changes to A are seen in B immediately. Nonetheless:
Private Sub dgv1_CellClick(sender As Object,
e As DataGridViewCellEventArgs) Handles dgv1.CellContentClick
If dgv2.Rows.Count = 0 Then Exit Sub
dgv2.CurrentCell = dgv2.Rows(e.RowIndex).Cells(e.ColumnIndex)
End Sub
Here, dgv1 is the user grid, dgv2 is the other ("parent" in your code?).
The For/Each iteration is not needed if they share a DS because the same data will be at each row and each column index. It will work even if the user has reordered the columns because the column index stays the same, just an internal DisplayIndex changes.
This uses the row and column indices from the DataGridViewCellEventArgs to set the CurrentCell. The Exit Sub is to account for starting up when one may have rows and not the other.
You may want to play with which event to respond to. CellContentClick seems least useful: if they click on any cell whitespace, it doesnt fire. It will also crash if the can click on a cell in the parent/dgv2 grid. CellEnter will also crash if they click on dgv2 directly.
CellClick seems to work okay, but there is the very slightest of delays before they synch up.

Stopping blank cells in a datagridview - VB.NET

I have a DataGridView on one of my forms that the user can edit and then update so changes are made to the database it is linked to. For this reason i do not want any of the cells to be left blank. Currently i am using this code:
If datagrdSnippets.Item(e.ColumnIndex, e.RowIndex).Value Is Nothing Then
' Show the user a message
MsgBox("Please ensure the cell has been given a value")
' Fail validation (prevent them from leaving the cell)
e.Cancel = True
End If
In the cell validating property of the DSG, however when i edit a cell and leave it blank nothing happens. Is there something wrong in my code or do i need to use another method?
Please Note: This is in VB.NET and i am currently using the CellValidating event.
Thanks :)
Value is not the property to be checked in the CellValidating Event, but e.FormattedValue. The Value property you are using in your code does not reflect the current cell value, but the last validated one. Sample code:
Private Sub datagrdSnippets_CellValidating(sender As System.Object, e As System.Windows.Forms.DataGridViewCellValidatingEventArgs) Handles datagrdSnippets.CellValidating
If (e.FormattedValue = "Value I want to avoid") Then e.Cancel = True
End Sub
Note that this event is called more than just when the user inputs a value and thus a MsgBox "without any restriction" shouldn't be put here (you have to set something (boolean flags, for example) making sure that the user is the one provoking this method to be called).