Rows Not Highlighting in Data Grid View - vb.net

I have a simple selection form that displays a DataGridView and allows the user to select a record to process. I have a short sub routine that loops through the DGV and highlights rows based on a date comparison with a dictionary when the form loads. This works great the first time I open the form, but on subsequent form opens, the grid doesn't highlight. When I step through the code it looks like the rows should be highlighted, but when the form displays, nothing is highlighted.
Here is the code I'm using. I cannot figure out why it doesn't always work. Is there a better, more reliable way to accomplish this?
For Each row As DataGridViewRow In dgvPending.Rows
For Each pair In dPending
If row.Cells.Item("ID").Value = pair.Key Then
If row.Cells.Item("LAST_UPDATED").Value > pair.Value Then
row.DefaultCellStyle.BackColor = Color.BlanchedAlmond
End If
End If
Next
Next

Related

Getting reference to control from function

My application has a form which contains 4 tabs and each tab has a DataGridView (DGV) within it. There is also a panel of controls which sit outside of the tabs and are used for all the DGV controls.
I need to make sure that the code updates the correct DGV based on what the user is looking at. I currently do this for any events or functions where I need to do some work on a DGV:
Dim dgv As DataGridView = GetCurrentDGV(TabControl.SelectedTab)
For Each row As DataGridViewRow In dgv.SelectedRows
'Do work on row
Next
And this is the function GetCurrentDGV():
Private Function GetCurrentDGV(ByRef tab As TabPage) As DataGridView
For Each control As Control In tab.Controls
If control.GetType Is GetType(DataGridView) Then
Return CType(control, DataGridView)
End If
Next
End Function
There are a number of things I don't like about this.
Firstly, it is slow. I'm not exactly sure why as each tab only contains a DGV and nothing else (so the loop through controls is only a single item which should return on the first loop).
Secondly, there's a chance my function doesn't return anything which will give a null reference.
I am trying to avoid hard-coding the relationship between tabs and DGV but before I go down that route, are there better ways I could be doing this?

DataGridView: EditOnEnter selection mode allowing row deletion

By default, a DataGridView is set to EditOnKeystrokeOrF2 edit mode. This means two or three clicks (spaced further apart than the user's double click interval) are required to change the value of a combobox in this view. As this is rather strange for a UI object, you would tend to think the control doesn't work.
Fortunately, you can change the selection mode to EditOnEnter. This will immediately select a cell when clicking on it, not first select the row, reducing the amount of clicks by 1. However, DataGridViews are implemented somewhat strangely. There is a '-1th' cell that is not manually selectable in each row.
When this '-1th' cell is selected, in the normal selection mode the row is selected, but in the "EditOnEnter" mode the 1st cell in the row is selected instead. If the DataGridView is set to enable row deletion using the "Del" key, then using EditOnEnter makes it impossible to use this functionality.
How do I get both to work? I.e.: I don't have a view where the user can have click up to 6 times (users tend to click more rapidly when they have to do so a lot of times) to open a box, while at the same time allowing row selection using the special -1th column?
One would need to programmatically toggle between both edit modes when any cell in the row is clicked. However, the CellClick event fires too late: after the row is already selected. Naively just toggling the EditMode would mean that the first click on the row selection box doesn't work, while the second would, which would appear as buggy behaviour.
The trick is to do much more manually. The following event handler, when attached to the CellClick event, will resolve almost all issues.
Private Sub CellSelect(ByVal sender As Object, ByVal e As DataGridViewCellEventArgs) Handles myDataGridView.CellClick
Dim dgv As DataGridView = CType(sender, DataGridView)
If dgv.Rows.Count = 0 Then
Return
End If
Dim rowToSelect As Integer = e.RowIndex
Dim columnToSelect As Integer = e.ColumnIndex
If e.RowIndex = -1 Then
rowToSelect = 0
End If
If rowToSelect >= dgv.Rows.Count Then
rowToSelect = 0
End If
If columnToSelect = -1 Then
dgv.EditMode = DataGridViewEditMode.EditOnKeystrokeOrF2
dgv.SelectionMode = DataGridViewSelectionMode.FullRowSelect
dgv.CurrentCell = Nothing
dgv.Rows(rowToSelect).Selected = True
Else
If columnToSelect >= dgv.Rows(rowToSelect).Cells.Count Then
columnToSelect = 0
End If
dgv.EditMode = DataGridViewEditMode.EditOnEnter
dgv.SelectionMode = DataGridViewSelectionMode.CellSelect
dgv.Rows(rowToSelect).Cells(columnToSelect).Selected = True
End If
End Sub
It works by unsetting the selected cell, then setting the selected row programmatically. As the EditMode was changed beforehand, it will select the entire row, not just the first cell, even the first time that the row-selection box is clicked.
There are also a whole bunch of edge cases where a user that clicks quickly enough can create click events on cells that do not exist. So we assume those clicks are on the cell [0,0] so at least our application won't blow up.
This isn't a perfect solution (yet). With this solution: A small graphical glitch remains; for about one frame the DataGridView will flicker between edit modes, very briefly appearing as though the row is selected.

MS Access VBA - First Record In List is Overwritten on Form Close?

I just learning how to create forms in Microsoft Access 2013 and using VBA programming to control but I'm having an issue I don't quite understand.
I have created a form with a List Box where the source originates from a query that contains the following fields the Query Builder in order from left to right:
|ParentNumber|ParentName|ChildNumber|ChildName|
|------------|----------|-----------|---------|
|------------|----------|-----------|---------|
|------------|----------|-----------|---------|
Some fields from the Query are hidden with a Column Width of 0".
I also have 4 Text Box below the List Box corresponding to the appropriate ParentNumber, ParentName, ChildNumber, and ChildName values.
When I select a record in the List Box, it populates the data to the appropriate Text Box.
When the form first loads, the first row in the List Box is selected:
Private Sub Form_Load()
On Error Resume Next
DoCmd.GoToRecord , , acFirst
Me.List = Me.List.ItemData(0)
End Sub
The issue is that if I select a different row, then close the form, and reopen the form, the first row in the List Box is overwritten with the last selected row before the form is closed.
Even if I start out with any other row selected initially when the form opens, the first row is always overwritten by the last selected row when the form is closed.
The following subroutine handles the update of the Text Box data:
Private Sub List_AfterUpdate()
Dim rowIndex As Integer
rowIndex = Me.List.ListIndex
Me.textBox_ParentNumber = Me.List.Column(3, rowIndex)
Me.textBox_ParentName = Me.List.Column(4, rowIndex)
Me.textBox_ChildNumber = Me.List.Column(6, rowIndex)
Me.textBox_ChildName = Me.List.Column(7, rowIndex)
End Sub
I found a somewhat similar problem to mine, but I tried the suggested solution, which didn't seem to work: MS Access - First record in table is overwritten on form close
I'm completely baffled as to what could cause this based on the code above.
What's my issue?
Thanks.
Few things
Private Sub Form_Load()
'remove this so you can see errors.
'On Error Resume Next
' this goes to the first record of the *form*, not the list.
' you might want this, or not.
DoCmd.GoToRecord , , acFirst
' ItemData returns the data in the *bound column* of the list,
' the data from one specific column. the list is set to that
' data every time the form loads. not what you want; remove it.
'Me.List = Me.List.ItemData(0)
End Sub
This should get rid of the problem. What you want to do next is another question.
Your form should be bound to a record set (table or query).
I had same problem, After hours of verification -
In my case - the problem was that the MainForm , And SubForm (table) - was binded to the same recordset. I just Un-Binded data RS from MainForm.

Adding unique records to a listbox from another listbox

I am hoping someone can help me out because I don't often code in Excel VBA. I have two Listbox and a CommandButton on a UserForm, which adds selected records from the first ListBox to the second. The range in the first ListBox is kind of long and so users of the form will generally select a couple records, hit the Add button, and then scroll down the first ListBox to select more records to add. The problem is, only the ones that have been added last will actually be recognized and used to generate reports even though all of the selected records appear in the second ListBox. Here is my current code for the button that adds the records to the second ListBox:
Private Sub AddButton_Click()
For i = 0 To Listbox1.ListCount - 1
If Listbox1.Selected(i) = True Then Listbox2.AddItem Listbox2.List(i)
Next i
End Sub
How can I populate the second ListBox so that it will include every record selected no matter how many times the add button is used?

showing iteration through a DataGridView, updating the display/redraw

I have a DataGridView with a single column that currently displays a short list of items. When the user clicks a button to run an update, each row/cell is read and processing begins.
I would like to have the selection indicator move down the rows in the DataGridView as it completes processing of each record. How can I display the iteration of the DataGridView rows while the processing is underway? A redraw of the DataGridView or something.
This is a VB.net windows form, I know how to do this with AJAX I think, but how can I achieve this in a Windows form?
Thanks,
For each row As DataGridViewRow in myDataGridView.Rows
'Unselect previous row, then select current row
myDataGridView.ClearSelection()
row.Selected = True
myDataGridView.Refresh()
'Do processing here...
Next
This will select each row but won't scroll down if the current row is out of view. To scroll down automatically you can set the DataGridView FirstDisplayedScrollingRowIndex property.