For Loop to count checked items on datagrid not counting correctly - vb.net

I worked out the following loop to count and display how many rows on my datagrid are checked. However, the loop is ignoring my first checked row. The count does not start at 1 until I have checked the second row. The same happens when I uncheck, the values are off by one.
Dim chkRowCount As Integer = 0
For Each row As DataGridViewRow In dgvAssignGridView.Rows
If row.Cells(6).Value = True Then
chkRowCount += 1
Else
chkRowCount += 0
End If
Next
lblChkCount.Text = chkRowCount.ToString
I have tried setting the variable to 1 instead of 0, but that had some unwanted results.

I am guessing you have this code in CellContentClick. The problem is that the code in that routine fires before the value of the checkbox is actually changed. However, you can basically force the DataGridView to verify itself first by putting the following line right before your code.
dgvAssignGridView.EndEdit()
That forces the cell click to register before you do your count.

Related

DataGridView Select Row with Specific Cell value [VB.NET]

I am using this code to move the row selection programmatically
For Each row In DataGridView1.Rows()
If row.Cells(0).Value.ToString().Equals(code) Then
row.Selected = True
End If
Exit For
Next
But the Problem I am facing is This only Changes the highlighted row but doesn't actually select the row..
When I try to get data from selected row it gives data from previous row not the blue highlighted row.
Actually Row header Tick type thing doesn't move It stays on previous row.
You also have to set the selceted cell:
For Each row As DataGridViewRow In DataGridView1.Rows()
If row.Cells(0).Value.ToString().Equals(code) Then
row.Selected = True
DataGridView1.CurrentCell = row.Cells(0)
Exit For
End If
Next
The reason your code works only for the first row is that Exit For was outside the If statement. If you include it the code works like a charm.

Compare DataTable and DataGridView and hightlight matching rows in DataGridView

I have a database table which contains a list of usernames and their current active location, an integer called SEQUENCE.
I get this list of sequence numbers into a datatable with a single column (e.g. "SELECT SEQUENCE FROM TABLE"):
dtUsers = CLS_USERS.GetUsers(User)
It excludes the current user, which is why I parse in User.
What I then do is loop through the datatable and for each number I want to set the matching row in a datagridview (which also has a SEQUENCE column) to a different colour. This is my current code:
For Each row As DataRow In dtUsers.Rows
intSeq = row("SEQUENCE")
For Each dgv_row As DataGridViewRow In dgvCandList.Rows
If dgv_row.Cells("CURRENT_SQ").Value = intSeq Then
dgv_row.DefaultCellStyle.BackColor = Color.Cyan
Else
dgv_row.DefaultCellStyle.BackColor = Color.Grey
End If
Next
Next
However, all rows are highlighted rather than just those where dgv_row.Cells("SV_CURRENT_CAND_SQ").Value = intSeq is True... I've verified that this loop is working correctly, so it must be dgv_row.DefaultCellStyle.BackColor = Color.Cyan which is incorrect?
If so, how should I correctly be assigning the row back colour of specific DataGridRow?
EDIT: This code works correctly, my issue was related to bug outside this loop causing the BackColor to be sent for everything, and then never setback to default if where BackColor wasn't being set back to the default if it wasn't in dtUsers.

Not getting all rows when iterating through DataGridView rows

In a VB.NET WinForms application I have a DataGridView with a checkbox as a non-bound column in the first column. I need to add to a collection of rows each row that has its checkbox checked.
I'm using the below code to iterate through the rows and find the ones with a checked checkbox:
For Each row As DataGridViewRow In dgvEmployees.Rows
Dim chkCell As DataGridViewCheckBoxCell = DirectCast(row.Cells(0), DataGridViewCheckBoxCell)
If Convert.ToBoolean(chkCell.Value) = True Then
Console.WriteLine("This should be the Emp No of the checked row: " & row.Cells(1).Value.ToString())
End If
Next
But it is missing the last row with a checked checkbox. I.e. If I check three checkboxes, in the console output I'm seeing the "Emp No" of the first two checked rows.
Thinking it was acting like an issue with zero indexing, I also tried doing an iteration that used a counter:
For rowNum As Integer = 0 To dgvEmployees.Rows.Count - 1
Dim currentRow As DataGridViewRow = dgvEmployees.Rows(rowNum)
Dim chkCell As DataGridViewCheckBoxCell = DirectCast(currentRow.Cells(0), DataGridViewCheckBoxCell)
If Convert.ToBoolean(chkCell.Value) = True Then
Console.WriteLine("This should be the emp no of the checked row: " & currentRow.Cells(1).Value.ToString())
End If
Next
But I get the same behavior with that code. I tried changing around the Integer = 0 and Rows.Count - 1, etc but that didn't help either.
In case it matters, the DataGridView's SelectionMode needs to be set to CellSelect.
UPDATE
There are 694 records in the table that the datagridview is being populated by.
I added a console output to get the rows.count value:
Console.WriteLine("Num rows: " & dgvEmployees.Rows.Count)
and got 695, which makes sense due to the last row in the datagridview is there to allow entry of a new row. (But I would have thought that the Count - 1 in the second iteration method would account for that.)
I also added
Console.WriteLine("Row index: " & chkcell.RowIndex)
right before the If check for a checked checkbox and, with the first, third and fifth rows checked (indexes 0, 2, 4), here's what was output:
Num rows: 695
Row index: 0
this should be the emp no of the checked row: ACS175
Row index: 1
Row index: 2
this should be the emp no of the checked row: AJAW03
Row index: 3
Row index: 4
Row index: 5
Row index: 6
There should have been a "this should be..." output after the Row index: 4 line.
It appears that the last check box that you check is not being committed by the DataGridView because you aren't moving the focus to another cell after checking it. Try this before running your iteration code:
If dgvEmployees.IsCurrentCellDirty Then
dgvEmployees.CommitEdit(DataGridViewDataErrorContexts.Commit)
End If

How to delete empty datagridview cells on import

Currently I have my program hiding blank or empty datagridview cells. I want to find a way to delete these cells entirely. The reason being, after the blank cells were hidden they would reappear after going through some of my other validations. These validations checked to see if the cells contained any invalid input such as negative numbers,non-numeric input and blank cells. If they contained any of the above they would be populated with default values, thus making my hidden cells reappear. Hopefully if there is a way to delete these cells they won't have a change of getting filled with default data. I've found the below code on MSDN but it doens't seem to work properly for whatever reason. Also I'm using the DATABINDINGCOMPLETE event. I'm not sure if there is another event that would work better for this situation. I greatly appreciate any help you may give!
Private Sub DataGridView1_DataBindingComplete(sender As Object, e As DataGridViewBindingCompleteEventArgs) Handles DataGridView1.DataBindingComplete
Dim i As Integer = 0
Dim mtCell As Integer = 0
For Each row As DataGridViewRow In DataGridView1.Rows
For j = 1 To row.Cells.Count -2
If row.Cells(j).Value Is DBNull.Value Then
mtCell += 1
End If
Next
If mtCell = row.Cells.Count Then
DataGridView1.Rows.RemoveAt(i)
End If
i += 1
mtCell = 0
Next
end sub
There are various problems with your code. Here you have an improved version which should work without any problem:
Dim mtCell As Integer = 0
Dim row As DataGridViewRow = New DataGridViewRow()
For rowNo As Integer = DataGridView1.Rows.Count - 2 To 0 Step -1
row = DataGridView1.Rows(rowNo)
Try
For j = 0 To row.Cells.Count - 2
If row.Cells(j).Value Is Nothing OrElse row.Cells(j).Value Is DBNull.Value Then
mtCell += 1
End If
Next
If mtCell = row.Cells.Count - 1 Then 'I understand that you want to delete the row ONLY if all its cells are null
DataGridView1.Rows.RemoveAt(rowNo)
End If
mtCell = 0
Catch ex As Exception
Exit For
End Try
Next rowNo
First thing, it is better to iterate the Collection "backwards" when deleting in order to avoid problems (example: 3 rows; you delete the first position and the loop goes to the second one; but after the deletion all the rows "move up" and thus the second position is now occupied by the third row -> you would skip the second row and, eventually, iterate beyond the limits of the Collection). DBNull.Value is quite restrictive; not sure if it is working fine under your specific conditions, but better complementing it with Nothing. You cannot affect the item being iterated in a For Each loop (unlikely in a normal For one); in this case you are affecting it indirectly but just to make sure, better relying on a normal For loop. You are iterating through rows but you are not deleting these rows, but the ones defined by a counter (i) which is not necessarily related to the current row number, better getting rid of it. Lastly I have included a try...catch to make sure (that you don't access an inexistent position).

How to find the number of expanded/collapsed master rows and grouped rows in a DevExpress GridView?

I am currently using DevExpress 10.2 within Visual Studio 2010. In a previous question I was trying to print the current user view of a DevExpress GridControl with the user's choice of expanded or collapsed master rows and/or group sections. I was told this was not possible at this time. I have now decided to use the following code:
gvPOinvoiceBanded.OptionsPrint.ExpandAllGroups = False
gvPOinvoiceBanded.OptionsPrint.ExpandAllDetails = False
when I want it to be completely collapsed while printing as by default these are set to true.
I was just wondering if there is someway to check either the total number of expanded master rows or the total number of collapsed master rows. I would also like to do the same thing for the groups as you can have the groups expanded while the master rows are not.
You can get the number of expanded group rows using a loop like this:
Dim ExpandedGroupCount As Integer = 0
Dim Handle As Integer = -1 'group rows have negative row handles
Do Until GridView1.GetRow(Handle) Is Nothing
If GridView1.GetRowExpanded(Handle) Then
ExpandedGroupCount += 1
End If
Handle -= 1
Loop
'Do whatever with expanded group count
MsgBox(String.Format("Number of Expanded Group Rows: {0}{2}Number of Group Rows: {1}",
ExpandedGroupCount, Math.Abs(Handle + 1), Environment.NewLine))
Similarly, you can do this to get the count of expanded master rows:
Handle = 0
Dim ExpandedMasterRowCount As Integer = 0
Do Until GridView1.GetRow(Handle) Is Nothing
If GridView1.IsMasterRow(Handle) Then
If GridView1.GetMasterRowExpanded(Handle) Then
ExpandedMasterRowCount += 1
End If
End If
Handle += 1
Loop
MsgBox(String.Format("Number of Expanded Master Rows: {0}", ExpandedMasterRowCount))
Of course, if you are only checking so that you can see if you need to set the collapse this probably isn't worth the effort. There is no direct property that provides the counts you are looking for.
You could also probably use the events that fire when rows are collapsed and expanded to track the count as it changes. You have to be careful with that though because the event only fires once when expand or collapse all happens. So if you go with that method be sure to check the rowHandle in the event arguments parameter for GridControl.InvalidRowHandle. That is the value used in the case of collapse or expand all.