Unbound DataGridView add row with checkbox error - vb.net

This is a Windows forms program. I have an unbound DataGridView control with four columns; Feature ID as string, Parts as string, Flats as string and ShowOnEst as boolean. The columns were defined in the form designer and the boolean column is, indeed, set to be a checkbox with tristate set to false.
The user selects a product from a list box and this code is executed to populate the grid
grdFeat.Rows.Clear()
For i = 0 To curProduct.lstFeatures.Count - 1
With (curProduct.lstFeatures(i))
grdFeat.Rows.Add(.FeatureId, .Parts, .Flats, .ShowOnEst)
End With
Next
If AllowUserToAddRows is false, everthing is good. Setting AllowUserToAddRows to true, however, results in the following error:
FormatException
Value '' cannot be converted to type 'Boolean'.
The error is NOT triggered in my code. It's displayed in a new tab titled "No Source Available".
It seems pretty clear that the process that adds the new editing row is trying to set the checkbox to a string value, or perhaps NULL. I'm very new (a few months) to vb.net, so I suspect I'm overlooking some simple setting somewhere, but after several hours of trying to find it, I'm starting to feel a little foolish here.
I'd give you a list of things I've tried already, but it's a long one. :) I even tried to go around the issue by adding a new row manually, .add("","","",False), but that too gives the same error, even though I'm telling it what to put in the checkbox.
What am I missing? Also, can someone point me to an explanation of how that new editing row thingy works?

From what you explained, I have no real explanation for the problem.
A workaround may be to set AllowUserToAddRows to false before populating the DataGridView and set it to true after.

Found it. Hope it helps someone else...
The rows being added are uncommitted rows. To solve it, capture the row added index, set the current cell and notify that the added row is dirty:
grdFeat.Rows.Clear()
For i = 0 To curProduct.lstFeatures.Count - 1
With (curProduct.lstFeatures(i))
Dim p = grdFeat.Rows.Add(.FeatureId, .Parts, .Flats, .ShowOnEst)
End With
grdFeat.CurrentCell = grdFeat.Rows(p).Cells(0)
grdFeat.NotifyCurrentCellDirty(True)
Next
Well, with further experimentation, this isn't a total fix. The problem is still there, but at least now handling the DataError event allows me to do something with it in code. Without these lines, the error occurs before the DataError event is triggered.
Still puzzled.

Related

VB.Net ComboBox (as Dropdown) not translating text to DisplayMember with Databinding

I inherited a fairly large project at work that is undocumented and written in VB (originally started pre .NET, ended around .NET 2). I'm in the process of updating / refreshing a lot of the code, but have run into an annoying issue that I haven't found the solution for yet. This system utilizes a UI, a Web Service, and a SQL DB.
Problem: I have a Databound Combobox (originally set to DropDownList - I'm changing it to DropDown, which is what started this mess - going back isn't an option) that is tied to a DataSet that comes from a Web Service. When a user types in the item they want manually, the data from the text field doesn't seem to associate itself with the DisplayMember, which forces the WS/SQL query to fail (it is sent a blank value when it's expecting a ValueMember). If the user types in a partial selection and then chooses the value they want from the DisplayMember list using the arrow keys or tab, the query goes off without a problem.
My Question: How do I get the text field to translate to the DisplayMember which will then properly tie itself to the ValueMember which will then allow the query to execute correctly? Sorry for making this sound complicated or convoluted; I'm sure the answer is easy and I'm just glazing over it.
The relevant bit of code is:
With cmbDID
If dtsLU.Tables.Contains(reqTable) = True Then
.DataSource = dtsLU.Tables(reqTable)
.DisplayMember = "zip"
.ValueMember = "gridID"
End If
End With
cmbDID.DataBindings.Clear()
cmbDID.DataBindings.Add("SelectedValue", dtsData, strDT & ".gridID")
I've tried changing "SelectedValue" to "Text", which almost works - but it directly translates to gridID and skips zip which ends up with an incorrect Web Service response since the zip and gridID field values are not synced (zip (DisplayMember) may be 5123 while gridID (ValueMember) may be 6047). I've tried changing "SelectedValue" to "SelectedIndex", and that got me no where.
Any help is greatly appreciated.
EDIT
To add some clarification to the process, the below pseudo code / description is roughly what happens. I could post the whole module, but I feel that would just muddy the whole question even more.
Private Sub A
FormAlpha is created with 1 ComboBox in the form of a DropDown
This DropDown is populated with a DataSet
DataBinding with a blank DataSet is added to the control to keep track of the users input
End Sub
lblSubmit_Click event is triggered on FormAlpha by the user after they have populated the DropDown with their data. lblSubmit_Click calls Private Sub Submit
Private Sub Submit
BindingContext(DropDown DataSet, tableName).EndCurrentEdit() is called
DataSet.HasChanges() is processed
If changes are present, changes are processed
HERE lies the problem
If the user has manually typed in the DropDown field, but not hit an arrow key or tab, then the DataSet registers a change, but returns a null value in all fields - it knows something was entered, but that data apparently didn't pass through the DataSet for the ComboBox (ListItems or SelectedIndex didn't change / fire I'm guessing). If the user selects the item with the arrow keys, the DataSet has the proper input (I'm assuming the Data was validated by the control at this point).
If the processed data is good, a value is entered into the database
If the processed data is bad (empty), an error is returned
End Sub
If the above can't be solved with what I've provided, but someone still knows a better way to handle this type of situation, I'm all ears. Rewriting the module isn't ideal, but fixing this problem is a necessity.
Alright, while this fix may not be ideal, it is a fix none the less.
The bare bones problem was that the text value of the DropDown wasn't causing the data to actually affect the SelectedIndex / SelectedValue of the control unless you interacted with it using the arrow keys or a mouse click. So, while the DropDown would read "1234", in reality the control saw "".
The fix I have in place for this is simply calling comboBox.text = comboBox.text whenever the user hits the submit button.

Checkbox in a DataGridView column is not getting checked sometimes?

I use this code to check all the check-boxes in a data grid view in VB.NET (2010 - .NET Framework 4.0),
Dim i As Integer
For i = 0 To (DataGridView.Rows.Count - 1)
DataGridView.Rows(i).Cells(0).Value = True
Next
Sometimes when one of the row is selected (not checked but just the entire row is selected) while this code is running, it checks all other check-boxes in the column except the selected one. What is wrong here?
I also try adding this code,
DataGridView.SelectedCells(0).Cells(0).Value = True
Did not work.
Like I said in the comments, the issue is that the box is checked in the datasource, but the GUI hasn't refreshed that cell to reflect it. If you click off of it, the cell should change/refresh to your new value. After you have made your data changes, at the very end you should deselect cells/rows. You can do it by:
Datagridview.ClearSelection()
or
Datagridview.CurrentCell = Nothing 'deselects
You get the idea. This is what has worked for me in the past.

VB.NET BindingSource cannot be its own data source ... error in a datagridview

I'm trying to make a search inside a datagridview, looping through every cell and comparing 2 strings - SearchString and CellString.
I divide the work into four threads (by giving each thread a different quater of the rows to work with) that work in parallel. Threads CANNOT read one and the same cell at the same time, because they loop through different rows, so I don't think the error's there.
Each thread does the following:
dim CellString as string
For i As Integer = startrow To endrow
For Each cell As DataGridViewCell In DataGridView.Rows(i).Cells
CellString = cell.Value.ToString.ToLower ''Error appears here
If cell.ColumnIndex <> 4 Then
Select Case Compare(CellString, SearchString) ''complex function that compares 2 strings
''....
End Select
End If
Next
Next
The error I get is :
BindingSource cannot be its own data source. Do not set the DataSource and DataMember properties to values that refer back to BindingSource.
I don't get why this happens because i don't mess with the BindingSource nor with the DataSource. Also I don't do any updates I only read every cell as a string.
I couldn't find any similar problem, so any help is appreciated !
Without seeing your whole code, it is hard to answer the question exactly but everything points to the fact that you are trying to access some elements of your UI (which Datagridview is part of) from the threads that you are creating.
According to Microsoft, this is not legal:
By design, Windows Form or Control methods cannot be called on a thread other than the one that created the form or control
Check this article for more info. It helped me resolve the similar issue.

Assigning DataGridView_1 (DGV) to DGV_2 and DGV_2 doesn't update

I have successfully found an answer to every question I ever had since I started with VB.NET 2 years ago by trawling forums, but this time I failed, and I decided to join my favourite forum where I have always found the best answers. This one :-)
I am somewhat of a beginner, so load you flack-guns 'cause here we go...
In my main form I have a DGV (called "gridDisplay") to display data. This DGV is a read only one as it is only used to disply data, not to inteact with it.
I have any number copies of a class (called "TaskData") that holds data to be displayed, and the data to be shown in the main form is that of the active "TaskData" class.
I came up with the brilliant (I have my doubts now...) idea to let the TaskData class make a DGV as it knows what data is in it and how to display it, and then all I had to do in the main form was to set the DGV there to that of the Active TaskData Class (see code below)
With ActiveTask
'Assign the active DataDisplay to the one in the main form
Me.gridDisplay = .TaskData.DataDisplay
Me.gridDisplay.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders
Me.gridDisplay.Refresh() 'Trying to make it update
Me.gridDisplay.Update() 'Trying to make it update
MsgBox("Row count: " & Me.gridDisplay.RowCount)
End With
Ok, so the DGV in the .TaskData.DataDisplay has one column and 500 rows. The One in the main form is set up with a default of 2 columns and no rows (set up in the designer)
After the code above, nothing happens visually in the main form. Still 2 columns and 0 rows. However, the text box says: "Row count: 500" And if I put a break point there I can inspect Me.gridDisplay and it has all the data that should be there.
Why doesn't it show up?
Am I doing something unwise by assigning one DGV to another?
Any help would be much appreciated.
Any constructive critizism equally so :-)
I think you should call the datasource again before
Me.gridDisplay.Refresh()Me.gridDisplay.Update()
Something like this,
gridDisplay.DataSource = dataset.Tables["your table"];

When adding a checkbox to a datagridview datatable I get dataerrors

I have a datagridview that I've added a checkbox column to. When I preview my data without the checkbox it works fine. when I run the program and try to load the datatable, I get a data error. I'm not sure what may be causing this. Where can I look to figure out what's causing this error?
Thank you
Doug
Your e.Context returns as Display. If you take a look at MSDN you will see for display it says
A data error occurred when displaying
a cell that was populated by a data
source. This value indicates that the
value from the data source cannot be
displayed by the cell, or a mapping
that translates the value from the
data source to the cell is missing.
In other words the checkbox column in the dgv probably doesn't quite know how to display the information you are giving it. So, chances are you are telling the checkboxes whether they should be true or false incorrectly.
Update: Perhaps, your solution lies with the TrueValue and FalseValue properties of DataGridViewCheckBoxColumn Class. These properties define when a checkbox should be checked or not checked. If you don't have these set, or if you are trying to set your checkboxes to something other than either of the two values in these properties, you would have problems.