Reading the value of the cell - vb.net

I have some DataGridView code written in vb.net. (Nothing is attached to a datasource.)
The 4th column is a checkboxCell. How do I detect if that checkBox is checked or unchecked?
This code strangely reports TRUE or FALSE at random times. It even turns ON the checkbox in rows other than the row I clicked in.
Private Sub DataGridView1_CellContentClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick
Dim whichGrid As DataGridView = CType(sender, DataGridView)
Dim rowClicked As Int16 = e.RowIndex
Call MsgBox(rowClicked & vbCrLf & whichGrid.Rows(rowClicked).Cells(4).Value)
End Sub
All the other examples I've looked at here (and elsewhere) don't seem to help. Their solutions are always:
Just check the cell's VALUE.
Just learn c#, and learn to convert it to vb.net.
Just check VALUE for nothing, or null, or "", or all of those.
Convert VALUE to a bool.
Attach it to a datasource instead.
Set TrueValue and FalseValue.
I've tried countless other methods, none seem to actually get the checkbox ON/OFF value in vb.net.

Cast the cell's value to a Boolean:
Dim RowIndex As Integer = ...
Dim ColumnIndex As Integer = ...
Dim IsTicked As Boolean = CBool(DataGridView1.Rows(RowIndex).Cells(ColumnIndex).Value)
If IsTicked Then
MessageBox.Show("You ticked the box.")
Else
MessageBox.Show("You cleared the box.")
End If

Related

Revert the DataGridViewCell to the value before it was changed by the user

I have a DataGridView like this:
The Quantidade column can be changed by the user and the others are read only. I came up with this code that if the user changes the value of Quantidade manually on the DataGridView it checks the database to see if it has enough in stock. So if the value inputted by the user is less than the total in stock it changes normally but my question is if the user inputs a value bigger than the value in stock I want the DataGridViewCell to return to the value before it has been changed by the user.
Any ideas on how to do this?
Here is the code of the event:
Private Sub DataGridView1_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellValueChanged
'this part is to check the total of the product in the db
Dim Produtoid As String = DataGridView1.Rows(e.RowIndex).Cells(0).Value
Dim tabelaqndDisponivel As DataTable = CAD.GetData("SELECT quantidadeExistenteProduto FROM Produto where idProduto = " & Produtoid)
'qntDisponivel is a integer that holds the total quantity of the product in the db
Dim qntDisponivel As Integer = tabelaqndDisponivel.Rows(0).Item(0)
If DataGridView1.Rows(e.RowIndex).Cells(2).Value <= qntDisponivel Then
'inserts normally
Else
'now here the value on cell "quantidade" should revert
End If
End Sub
Note that This DataGridView is pretty simple. It takes the value from the ComboBox Produto and text from the TextBox Quantidade
An alternative that I often use is to save it to the .Tag, every object has a .Tag and it saves declaring a variable globally if you want to use it throughout the code.
Whilst not necessarily shorter code it does prove very useful at times and overall is tidier in my opinion as you don't have to declare a variable (you can save it to the cell or row .Tag but that is even longer code).
Usage in your application:
Private Sub dataGridView1_CellValidating(ByVal sender As Object, ByVal e As DataGridViewCellValidatingEventArgs) Handles DataGridView1.CellValidating
DataGridView1.Tag = DataGridView1.Rows(e.RowIndex).Cells(2).Value
End Sub
Retrieval:
Else
'now here the value on cell "quantidade" reverts to the value before being changed
DataGridView1.Rows(e.RowIndex).Cells(2).Value = DataGridView1.Tag
End If
My answer is to provide some help on a few issues with your code. Since we have already discussed your question at hand and a fix has been implemented I think it would be worthwhile addressing these issues.
Turn Option Strict On:
Restricts implicit data type conversions to only widening conversions, disallows late binding, and disallows implicit typing that results in an Object type.
First DataGridView1.Rows(e.RowIndex).Cells(0).Value is type Object and so to resolve this we need to append .ToString() to it like so:
Dim Produtoid As String = DataGridView1.Rows(e.RowIndex).Cells(0).Value.ToString()
Second tabelaqndDisponivel.Rows(0).Item(0) and DataGridView1.Rows(e.RowIndex).Cells(2).Value are too type Object. With these I would handle using Integer.TryParse. You can then also check the Integer values correctly:
Dim qntDisponivel As Integer = 0
Dim qnt As Integer = 0 'You can give this a more meaningful name
If Integer.TryParse(tabelaqndDisponivel.Rows(0).Item(0).ToString(), qntDisponivel) AndAlso
Integer.TryParse(DataGridView1.Rows(e.RowIndex).Cells(2).Value.ToString(), qnt) Then
If qnt <= qntDisponivel Then
'inserts normally
Else
'now here the value on cell "quantidade" reverts to the value before being changed
DataGridView1.Rows(e.RowIndex).Cells(2).Value = valorqnt
End If
Else
'Haven't been able to check so revert
DataGridView1.Rows(e.RowIndex).Cells(2).Value = valorqnt
End If
Thirdly DataGridView1.Rows(e.RowIndex).Cells(2).Value inside your CellValidating method is again type Object. Change using Integer.TryParse:
Integer.TryParse(DataGridView1.Rows(e.RowIndex).Cells(2).Value.ToString(), valorqnt)
Lastly your SQL statement is open to SQL injection. You would need to look into SQL parameters. It's quite difficult to provide much help in this area as I can't see what GetData does and it would be outside the scope of this question but it is definitely worth a mention.
So what I did here was create a variable Private valorqnt As Integer and on the event CellValidating I saved the value (before being changed by the user) into it.
Code:
Private Sub dataGridView1_CellValidating(ByVal sender As Object, ByVal e As DataGridViewCellValidatingEventArgs) Handles DataGridView1.CellValidating
valorqnt = DataGridView1.Rows(e.RowIndex).Cells(2).Value
End Sub
This way I have the value of the cell before being changed. Now on the CellValueChanged event I added DataGridView1.Rows(e.RowIndex).Cells(2).Value = valorqnt so I could revert the value.
Code:
Private Sub DataGridView1_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellValueChanged
'this part is to check the total of the product in the db
Dim Produtoid As String = DataGridView1.Rows(e.RowIndex).Cells(0).Value
Dim tabelaqndDisponivel As DataTable = CAD.GetData("SELECT quantidadeExistenteProduto FROM Produto where idProduto = " & Produtoid)
'qntDisponivel is a integer that holds the total quantity of the product in the db
Dim qntDisponivel As Integer = tabelaqndDisponivel.Rows(0).Item(0)
If DataGridView1.Rows(e.RowIndex).Cells(2).Value <= qntDisponivel Then
'inserts normally
Else
'now here the value on cell "quantidade" reverts to the value before being changed
DataGridView1.Rows(e.RowIndex).Cells(2).Value = valorqnt
End If
End Sub

How to have $ sign show on a price textbox

Im coding in VB.Net and trying to have a textbox which displays price with a $ sign. I have gotten it to where the textbox would be empty and once the user puts in a number the sign would show. But I cant add it to the textbox which gets its data from the datasource. If you could lead me towards the direction to get it to show up in the textbox that would be great thanks.
You could try the reulting visual behavior of a MaskedTextBox control
With for example this mask:
MaskedTextBox1.Mask = "9999999999$"
Then, to get a integer value when the text has changed:
Private Sub MaskedTextBox1_TextChanged(sender As Object, e As EventArgs) _
Handles MaskedTextBox1.TextChanged
Dim mtb As MaskedTextBox = DirectCast(sender, MaskedTextBox)
Dim intValue As Integer
If Integer.TryParse(mtb.Text.Replace("$"c, "").Replace(" "c, ""), intValue) Then
Console.WriteLine(intValue)
End If
End Sub

I want to count checked checkboxes on datagridview when click on the checkbox not on button click

I want to count the number of checkboxes that are checked in a datagridview when a checkbox is clicked.
Here is my code:
Dim count1 As Integer = 0
For Each row As DataGridViewRow In dgvAtt.Rows
If row.Cells(1).Value = True Then
count1 += 1
End If
Next
txtCnton.Text = count1
I've called the above procedure in CellContentClick, CellValueChanged and CellStateChanged but it doesn't count properly.
There are two likely causes for the count of check boxes being different from what you expect. The most likely is that fact that the value of the check box column lags behind the check box state due to how datagridview editing controls commit their values when they lose focus.
The fix for that is to handle the CurrentCellDirtyStateChanged event as described here on MSDN.
So your code would become something like:
Sub dataGridView1_CurrentCellDirtyStateChanged( _
ByVal sender As Object, ByVal e As EventArgs) _
Handles dataGridView1.CurrentCellDirtyStateChanged
If dataGridView1.IsCurrentCellDirty Then
dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit)
End If
End Sub
And you CellValueChangedHander then changes to:
Public Sub dataGridView1_CellValueChanged(ByVal sender As Object, _
ByVal e As DataGridViewCellEventArgs) _
Handles dataGridView1.CellValueChanged
If dataGridView1.Columns(e.ColumnIndex).Name = "CheckBoxes" Then
Dim count1 As Integer = 0
For Each row As DataGridViewRow In dgvAtt.Rows
If row.Cells("CheckBoxes").Value IsNot Nothing And row.Cells("CheckBoxes").Value = True Then
count1 += 1
End If
Next
txtCnton.Text = count1
End If
End Sub
In the code above I also address the second likely cause of an incorrect count. In your code you reference datagridview cells by their index in the cells array. This is almost never the best way to do it. Instead each column has a name that you can use in the indexer.

how to put search functionality in dataGridView in vb.NET

How can I select a single cell from selected row in datagridView and after selecting that I want to put simple search functionality (like we have in our windows folders-typing any characters and search should work)?
I do not really understand your question. If you want to select one cell, you can use the celldoubleclick event for exemple. And the to get the selected cell, use e.rowindex and e.columnindex which will give you the row and the column where the cell is located.
You can try this as a possible solution.
Dim nwData as CustomersDataSet = CustomersDataSet.GetCustomers()
m_CustomersGrid.DataSource = m_CustomersBindingSource
m_CustomersBindingSource.DataSource = nwData.Customers
Then you can sort using the BindingSource.
CustomersBindingSource.Sort = "ContactName ASC"
And you can find using the BindingSource.
Dim index as integer = _
CustomersBindingSource.Find("CompanyName", CompanyNameTextBox.Text)
If index <-1 then 'it was found; move to that position
CustomersBindingSource.Position = index
End If
You could then populate:
CustomersBindingSource.Find("CompanyName", CompanyNameTextBox.Text)
with the keys pressed in the cell by capturing them by utilizing:
Private Sub DataGridView1_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles DataGridView1.KeyUp
Dim dgv As DataGridView = TryCast(sender, DataGridView)
If dgv IsNot Nothing Then
'You will need some logic here to determine how long to wait between keyups
'Perhaps a timer that ticks every500 milliseconds and reset on keyup.
e.KeyData
End If
End Sub
I found the original Biding Source Logic at : This Location

Capturing value of DataGridView CheckBox in VB.Net

I have a datagridview (unbound). Fields are Name, Family Name and Phone No and a checkbox colum.
There are ten rows in that DataGridView.
There is an OK button
I need to get message of showing which rows user has checked. The message should appear when user clicks on the OK button. There could be several messages, checking each row one by one, in a loop.
I am not able to get this message. I tried following code in OK button :
Dim strCB As String = dgvChooseQs.Rows(0).Cells(3).Value.ToString
Cell(3) is my checkbox. Do not consider Rows(0), at the moment I am just checking value at row 0
Thanks for your help.
Furqan
Do not use the cell index. Your checkbox column must have a name so you should use it.
Otherwise, what you want to do would be something like this
For each oRow as DataGridViewRow in dgvChooseQs.Rows
If oRow.Cells("ColNamE").Value = True then
'do whatever you need to do.
End if
Next
If you feel you need to cast the column, then you can use CType, but the type is DataGridViewCheckBoxCell, not CheckBox.
You need to do something like this:
if ctype(dgvChooseQs.Rows(0).findcontrol("whateverYourCheckBoxIsNamed"), checkbox).checked then
'throw the message
end if
You may cast the cell value to Boolean, and then check it, as follows:
Dim RowIndex As Integer = ...
Dim ColumnIndex As Integer = ...
Dim IsTicked As Boolean = CBool(DataGridView1.Rows(RowIndex).Cells(ColumnIndex).Value)
If IsTicked Then
MessageBox.Show("You ticked the box.")
Else
MessageBox.Show("You cleared the box.")
End If
Only the third example worked for me but I had to add a Timer
Private Sub DgvElencoFile_CellClick(sender As Object, e As DataGridViewCellEventArgs) Handles DgvElencoFile.CellClick
'Variabili gestione programma
Dim numerocolonnaSelezionata As Integer
Dim numeroColonnaSelezionataPerDowonload As Integer
Dim numeroRigaSelezionata As Integer
numeroRigaSelezionata = e.RowIndex
NumerocolonnaSelezionata = e.ColumnIndex
If NumeroRigaSelezionata < 0 Then
ClaFunzSgnSon.SegnaleSonoro(ClaFunzSgnSon.EnTipoSgnSon.ErroreImpostazioneDati)
GoTo FineSubFunz
End If
numeroColonnaSelezionataPerDowonload = -1
If DgvElencoFile.Rows(numeroRigaSelezionata).Cells(ClnDownLoad.Name).Selected Then numeroColonnaSelezionataPerDowonload = numerocolonnaSelezionata
If numeroColonnaSelezionataPerDowonload >= 0 Then
TimVisCheckDownLoad.Start()
End If
FineSubFunz:
End Sub
Private Sub TimVisCheckDownLoad_Tick(sender As Object, e As EventArgs) Handles TimVisCheckDownLoad.Tick
TimVisCheckDownLoad.Stop()
Dim isTickedOn = CBool(DirectCast(DgvElencoFile.CurrentCell, DataGridViewCheckBoxCell).EditingCellFormattedValue)
If isTickedOn Then
MessageBox.Show("You ticked the box.")
Else
MessageBox.Show("You cleared the box.")
End If
End Sub
I found a simple solution.
Just change the cell focus after click on cell.
Private Sub DGV_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles DGV.CellContentClick
If e.ColumnIndex = "Here checkbox column id or name" Then
DGV.Item(e.ColumnIndex, e.RowIndex + 1).Selected = True
'Here your code
MsgBox DGV.Item(e.ColumnIndex, e.RowIndex).Value
End If
End Sub
Don't forget to check if the column of your (ckeckbox + 1) index exist.
Set type of grid in dataGridView to 'DataGridViewCheckBoxXColumn' instead of DataGridViewCheckBoxColumn.
all problems will be solved
The post is old but it can help in need:
You have these three properties after casting your cell:
Private Sub YourDataGridView_CellMouseClick(sender As Object, e As DataGridViewCellMouseEventArgs) Handles YourDataGridView.CellMouseClick
Dim b, b1, b2 As Boolean
b = DirectCast(YourDataGridView.CurrentCell, DataGridViewCheckBoxCell).EditingCellValueChanged
b1 = CBool(DirectCast(YourDataGridView.CurrentCell, DataGridViewCheckBoxCell).EditingCellFormattedValue)
b2 = CBool(DirectCast(YourDataGridView.CurrentCell, DataGridViewCheckBoxCell).EditedFormattedValue)
End Sub
it's a long time since this question was sent, but can be useful this answer to anybody with the same issue. In my case, I used (I'm using your notation):
dgvChooseQs.Item(6, vCont).State
where 6 is the checkbox column number, in my case column 6. vCont is an iteration counter in a FOR NEXT loop. If State equals 32, checkbox was checked, else State will be zero. I hope this can be of help.