Capturing value in DG cell - vb.net

I have a DataGridView bound to a DataTable. How can I detect when a user enters a value into a cell, then populate a value into another cell?
If dataGridView3.CurrentRow.IsNewRow = True then
If Len(dataGridView3.SelectedRows(0).Cells(3)) = 7 Then
dataGridView3.SelectedRows(0).Cells(4).Value = "Surprise"
End If
End If
This code does not throw any errors but when the length is equal to 7, nothing happens in cell 4 (technically cell 5).

Cells(3) is a DataGridViewCell, but Cells(3).Value is a String (I presume). You're checking the length of the wrong object.
If Len(dataGridView3.CurrentRow.Cells(3).Value) = 7 Then
Also, Len() is an old function from the VB6 era. I highly recommed switching to the String.Length property instead:
Dim CellValue As Object = dataGridView3.CurrentRow.Cells(3).Value
If CellValue IsNot Nothing AndAlso _
CellValue.GetType() Is GetType(String) AndAlso _
DirectCast(CellValue, String).Length = 7 Then
A bit more messy solution perhaps, but the additional checks ensure that no exceptions are thrown by the If statement.

Related

Looking for better solution

I have the following code.
Surely there must be a better way of coding this using a for/next or something, but I just don't get it to work
If CheckBox1.CheckState Then bin(1) = "1" Else bin(1) = "0"
If CheckBox2.CheckState Then bin(2) = "1" Else bin(2) = "0"
If CheckBox3.CheckState Then bin(3) = "1" Else bin(3) = "0"
..
..
..
If CheckBox20.CheckState Then bin(20) = "1" Else bin(20) = "0"
OK, This should work, but bear in mind, it assumes that you have 20 CheckBoxes and that number will never change, and that the bin array will also never change the number of elements.
Private Sub SyncCheckBoxestoBinValue()
For i As Integer = 1 To 20
bin(i) = Math.Abs(CInt(CType(Me.Controls("CheckBox" & i), CheckBox).Checked)).ToString
Next
End Sub
An explanation might be in order here. Working from the inside out, here goes..
Me.Controls("CheckBox" & i)
This will refer to the control that matches CheckBox1 when i=1, CheckBox2 when i=2 etc. However, because that bit of code is designed to work with all kinds of control, it can only return it as an Object type rather than the specific type of control you're searching for.
To be able to do anything significant with that result, we need to tell the compiler that it's a CheckBox. So now we need to wrap that last bit of code in to this.
CType(Me.Controls("CheckBox" & i), CheckBox)
Now we have something that the compiler recognises as a CheckBox, we can work with it. So you want to find out of the CheckBox is checked or not. You've usedCheckstate, but personally I think it's a bit easier to useChecked` for this purpose. So ...
CType(Me.Controls("CheckBox" & i), CheckBox).Checked
This returns a result of True or False. In VB.Net this can also be seen as -1 (true) or 0 (false). although you want a 1 or 0 so that you can assign this value to your bin array. How we do this is as below
Math.Abs(CInt(CType(Me.Controls("CheckBox" & i), CheckBox).Checked)).ToString
Finally, your result of 1 or 0 is assigned to the element of bin that corresponds to the CheckBox number
That "should" do it.
Maybe make the check boxes a list and query the result by linq? For the sake of using linq for everything better readability, I mean.
Dim cbList = New List(Of CheckBox) From {checkBox1, checkBox2, checkBox3}
Dim binTmp As List(Of String) = cbList.Select(Function(chk) If(chk.checkState, "1", "0")).ToList()
bin = binTmp
You may also want to store the result as Boolean instead of "1","0" for further processing.

DataGridView, Change cell of a typed Column to another type

I'm trying to mix a column on a datagridview with 2 control types (Checkbox & TextBox), the data is coming from a Stored Procedure that I'm also writing so I have a little flexibility.
in the stored procedure I'm returning a blank column to act as a Selection column in the GridView, but I am encountering problems when trying to convert cells to the other type based on criteria......
I keep the problem is with the datatypes when converting between the control types, I have tried all sorts of different ways to convert value first, controls first, etc but nothing is working 100%.....
currently, I have the SP returning the string False in a column then in using this with the criteria to create a checkbox..... it works fine but the Value remains a string even after converting it to a Boolean, the datatype is also a Boolean on the checkbox but the value is String..... this has gone over my head now and I'm at a loss......
NewCntrl2 = New DataGridViewCheckBoxCell
NewCntrl2.Value = Convert.ToBoolean(DGV.Cells(0).Value)
NewCntrl2.ValueType = GetType(System.Boolean)
DGV.Cells(0) = NewCntrl2
this is the code converting the textbox-column cell to a checkbox cell
any ideas why the value of the checkbox is still a string ('False')...
the problem with what it's doing now is when I handle the cell click event I cannot check or uncheck the box using the Not Value technique
----EDIT----
This is the sub I'm using, it creates several different types of controls.
Public Sub posted_CreateControls()
Dim Cell_0 As String
Dim Cell_1 As String
Dim Cell_2 As String
Dim NewCntrl As DataGridViewButtonCell
Dim NewCntrl2 As DataGridViewCheckBoxCell
For Each Rw As DataGridViewRow In dgvPosted.Rows
With Rw
Cell_0 = .Cells(1).Value.ToString
Cell_1 = .Cells(2).Value.ToString
Cell_2 = .Cells(3).Value.ToString
'this column starts with a value 'False' returned by the SP,
'we don't want checkboxes on all rows and using false string was the only method
'i could find to easily do this
'if both assign and unassign id are present then we need a checkbox
Select Case Cell_0
Case String.Empty
.Cells(0).Value = String.Empty
Case Else
If Not Cell_1 = String.Empty Then
NewCntrl2 = New DataGridViewCheckBoxCell
NewCntrl2.Value = Convert.ToBoolean(.Cells(0).Value)
NewCntrl2.ValueType = GetType(System.Boolean)
.Cells(0) = NewCntrl2
Else
.Cells(0).Value = String.Empty
End If
End Select
'Create an Assign button for each row in columnindex 0(Assign) if ColumnIndex(2)(Edit) contains M, L or I
Select Case Cell_2
Case "M", "L", "I", "P"
NewCntrl = New DataGridViewButtonCell
.Cells(1) = NewCntrl
NewCntrl.Tag = Cell_0
NewCntrl.Value = "Assign"
End Select
'Create an UnAssign button in columnindex 1(UnAssign) if the value of columnindex 1(Unassign) is not empty
If Not Cell_1 = vbNullString Then
NewCntrl = New DataGridViewButtonCell
.Cells(2) = NewCntrl
NewCntrl.Tag = Cell_1
NewCntrl.Value = "UnAssign"
End If
'Create an Edit button on columnindex 2(Edit) if ColumnIndex 2(Edit) is not M, L or empty string
Select Case Cell_2
Case "M", "L", "P", vbNullString
'Do Nothing
Case Else
NewCntrl = New DataGridViewButtonCell
.Cells(3) = NewCntrl
NewCntrl.Tag = Cell_2
NewCntrl.Value = "Edit"
End Select
End With
Next
NewCntrl = Nothing
End Sub
This creates the checkboxes how I want them but the values remain as a string that is causing the cell. Click event to fail because I'm trying to set the checkbox value to true and the .value = not .value part is failing because for some reason the value remains a string but the checkboxes value type is in fact Boolean.....
Instead of returning false try returning:
`select CAST(0 as bit) as somefield`
Which will return a boolean field. I'd also recommend adding a check box column instead of adding the individual cells.

Control name from Variable or Dataset. (Combobox)(.items.add)(.datasource)

I've checked for hours but I can't seem to find anything to help.
I want to loop through tables and columns from a dataset and use the column name in a combobox.items.add() line, however the eventual goal is to fill the combobox from the dataset itself possibly in a combobox.datasource line.
The first problem is that I can't get the code correct to setup the combobox control where it allows me to use .items.add("") and in extension .datasource
Error Message = "Object reference not set to an instance of an object"
dstcopt is the dataset from a oledbDataAdapter .fill(dstcopt,"table") line (which returns correct values)
tc_opt is a tab name on a tab control where the comboboxes are
For Each dstable In dstcopt.Tables
For Each dscolumn In dstable.Columns
Dim colName As String = dscolumn.ToString
MsgBox(colName) 'This retuns "aantigen"
Dim cb As ComboBox = Me.tc_opt.Controls("cb_" & colName)
cb.Items.Add(colName)
'cb_aantigen.DataSource = dstcopt.Tables(dstable.ToString)
'cb_aantigen.DisplayMember = "aantigen"
'cb_atarget.DataSource = dstcopt.Tables(dstable.ToString)
'cb_atarget.DisplayMember = "atarget"
Next
Next
The second problem comes when I do it manually (which works) using the exact combobox names cb_aantigen and cb_atarget as seen in the comments.
The problem is that once the form is loaded and the cb's are filled with the correct values, I can't change the value in any single cb individually, when I change one value it changes them all (there is 15 comboboxes in total) I know this is down to using a dataset, but I don't know away to 'unlink them from each other or the dataset'
Not sure if I need to split this into 2 questions, but help on either problem would be appreciated.
EDIT:
After looking at only this section of code for a day. This is what I have come up with to tackle both the problems at once.
The combobox control not working was down to using a tab tc_opt instead of a groupbox gp_anti
The issue with splitting the dataset up into individual comboboxes, I've worked around by taking the value of each cell in the database and adding it separately, probably a better way to do it though
For Each dstable As DataTable In dstcopt.Tables
For Each dscolumn As DataColumn In dstable.Columns
Dim colName As String = dscolumn.ToString
Dim cb(2) As ComboBox
cb(0) = CType(Me.gp_anti.Controls("cb_" & colName), ComboBox)
cb(1) = CType(Me.gp_rec.Controls("cb_" & colName), ComboBox)
cb(2) = CType(Me.gp_nat.Controls("cb_" & colName), ComboBox)
For icb = 0 To cb.Count - 1
If Not (IsNothing(cb(icb))) Then
For irow = 0 To dstable.Rows.Count - 1
If dstable.Rows(irow)(colName).ToString <> Nothing Then
Dim icbitemdupe As Boolean = False
If cb(icb).Items.Contains(dstable.Rows(irow)(colName).ToString) Then
icbitemdupe = True
End If
If icbitemdupe = False Then
cb(icb).Items.Add(dstable.Rows(irow)(colName).ToString)
End If
End If
Next
End If
Next
Next
Next

Setting value to a not-existing array item?

Please take a look at the following code:
Try
Dim Reader As New System.IO.StreamReader(PositionsFileName)
Do While Reader.Peek() <> -1
Dim Positions() As String = Reader.ReadLine().Split("|")
If (Positions(0) Is Nothing) Or (Positions(1) Is Nothing) Or (Positions(2) Is Nothing) Then
' something
End If
Loop
Catch ex As Exception
ex.Source = Nothing
End Try
I am reading a file and expecting format something|something1|something2. I am trying to make it set "Nothing" to the array index which does not exists (the file format is broken), so that the If statement goes smoothly, but it seem I am doing it wrong. Can you give me some hints?
If you do Split("|") and there are only 2 items (for example, something|something1), Positions(2) will not be Nothing, it will just not be there. So your code will raise an exception, something about index out of bounds of the array.
If you need Positions(2) contain Nothing in this case, you code can look like this:
Dim Positions(2) As String
Dim tmpArray() As String = Reader.ReadLine().Split("|")
For i = 0 To UBound(Positions)
If i <= UBound(tmpArray) Then
Positions(i) = tmpArray(i)
Else
Positions(i) = Nothing
End If
Next
I assume that you only have three "Somethings" per valid line. If so, try writing your Positions() assignment like this:
Dim Positions() As String = Reader _
.ReadLine() _
.Split("|") _
.Concat(Enumerable.Repeat("Nothing", 3)) _
.Take(3) _
.ToArray()
This will ensure that you have three items every time. No need to check for nothings.
Just check positions.length after the split. Also, if you want to check for cases like "||Something2|Something3", the first position will be "" not Nothing. The orelse is a shortcircuit that will keep the latter condtitions from being evaulated if an earlier condition is met.
If Positions.length < 3 OrElse Positions(0) = "" OrElse Positions(1) = "" OrElse Positions(2) = "" Then
' something
End If

how to check if the cell value is nothing or not in vb.net?

i am using grid view in vb.net.
here is code...
If Not DataGridView1.SelectedRows.Count = 0 Then
i = DataGridView1.SelectedRows(0).Index
If DataGridView1.Rows(i).Cells(0).Value <> Nothing Then
namebox.Text = Trim(DataGridView1.Rows(i).Cells(0).Value)
salarybox.Text = DataGridView1.Rows(i).Cells(1).Value
End If
End If
now if the cell has nothing in it then it will show the exception....
like this...
Operator '<>' is not defined for type 'DBNull' and 'Nothing'.
this is code will be called when selected cell will be changed.
i trying to get the values of the selected cell and put that in in one text box.
You don't want to use the <> operator, you should us value IsNot Nothing to check if it IsNot Nothing or inversely Is Nothing to check if a value Is Nothing.
Also the reason is that there is no comparer for the DBNull and Nothing Types so if this is the case you will need to check to see for both. Something like
If value IsNot Nothing AndAlso value <> DBNull.Value Then
''#Do something
End If
Change
If DataGridView1.Rows(i).Cells(0).Value <> Nothing Then
to
If Not DataGridView1.Rows(i).Cells(0).Value Is DBNull.Value Then