row cannot be programmatically added - vb.net

I'm trying to populate a datagrid view with the contents af a text file i used the following code:
Private Sub Button15_Click(sender As Object, e As EventArgs) _
Handles Button15.Click
'strPath is the location of text file
Dim lines = (From line In IO.File.ReadAllLines(strPath)
Select line.Split(CChar(vbTab))).ToArray
For x As Integer = 0 To lines(0).GetUpperBound(0)
dgQuotation.Columns.Add(lines(0)(x), lines(0)(x))
Next
For x As Integer = 1 To lines.GetUpperBound(0)
dgQuotation.Rows.Add(lines(x))
Next
End Sub
But every time i run the program i get the following run time error:
Rows cannot be programmatically added to the DataGridView's rows collection when the control is data-bound.
Please help, I'm new to VB. Thanks in advance.

It means you either need to use data binding or add rows manually - pick one, not both.

instead of the two for loops you can just set dgQuotation.DataSource = lines ... adding values to the grid programmatically (as you do in your code) is not possible if the grid is data bound (=> DataSource is set)

Related

Searching through CheckedBoxLists for checked boxes

I am creating a simple application that would enable me to input information into some textboxes and then, after pushing a button (called Addbtn) combine those into one string. This string would be added to a checkboxlist called ConcernsChk. When one or more of these strings are completed, the user would click the appropriate checkbox and click a button (called CompleteSortBtn) which would transfer that string to another checkboxlist. The issue I'm having is that my checkboxlist items do not delete according to their checked status. They delete one at a time beginning from the top and moving down.
Here's the code in question:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles CompleteSortBtn.Click
Dim Disposition As String = ""
Dim i As Integer
If ConcernsChk.CheckedItems.Count > 0 Then
For i = 0 To (ConcernsChk.Items.Count - 1)
If ConcernsChk.GetItemChecked(i) = True Then
Disposition = ConcernsChk.Items(i)
DispositionChk.Items.Add(Disposition)
ConcernsChk.Items.Remove(Disposition)
End If
Next
Else
MessageBox.Show("Please add Concerns before marking them complete.")
End If
I keep getting an error thrown that I cannot equal 3 and I have no idea what to do from here. This is thrown whether there are 2 items in the checkboxlist or 10.
Long story short, when I push the CompleteSortBtn, I want the program to do 4 things: 1. search through ConcernChk 2. Find checked boxes 3. Send the checked boxes to DispositionChk 4. Delete the checked items from ConcernChk
My apologies for the long post and thank you for whatever help you can give.
You are iterating though items not checkeditems.... count will be different.
SINCE you are removing items from the list you ALSO need to do it bottom to top.
For i = (ConcernsChk.Items.Count - 1) to 0 step - 1
If ConcernsChk.Items(i).Checked Then
Disposition = ConcernsChk.Items(i)
DispositionChk.Items.Add(Disposition)
ConcernsChk.Items.RemoveAt(I)
End If
Next

VB Studio ListBox scrollbar position

Perhaps there's a better solution, but...
I am using a listbox to select multiple items, but the list contains 800+ items in alphabetical order. If I am selecting three items, for example, "Apples", "Oranges" and "Zucchini", I have to pull the scrollbar down or use the mouse wheel to scroll through the list.
Is there any way to "jump" to a location in the list to reduce the scrolling needed? For example, if I had a button for "D", the scroll list would jump down to the items starting with "D".
Any suggestions would be appreciated.
This should work as you need.
The second line searches through the listbox to find the first item that begins with the key you pressed. If no Items begin with that letter, the FindString function returns -1 or the same as ListBox.NoMatches ( which is a constant already defined in Visual Studio to make code more readable)
I've put the code into a separate sub so that it can be resused to apply to any listbox.
Private Sub ListBox1_KeyDown(sender As Object, e As KeyEventArgs) Handles ListBox1.KeyDown
Dim key As String = Chr(e.KeyValue).ToString
SelectlistBoxItemFromKey(ListBox1, key)
End Sub
Private Sub SelectlistBoxItemFromKey(ByRef lBox As ListBox, k As String)
Dim index As Integer = lBox.FindString(k)
If index > ListBox.NoMatches Then
lBox.SelectedIndex = index - 1
End If
End Sub

How to delete and clear the datagridview rows in vb 2010

I am developing a Point of Sale System in VB and using access as RDBMS. Everything went well however when it came to deletion i got stuck. I want to clear all the rows from the datagridview and want to delete it from database also. The new datagridview will store new items and i am sending that new data to print.I tried the below codes but all in vain.
Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
For i As Integer = 0 To SProductDataGridView.RowCount
SProductDataGridView.Rows.Remove(SProductDataGridView.Rows(0))
Next
End Sub
2nd Try
For i As Integer = 0 To SProductDataGridView.RowCount -1
ProductTableAdapter.DeleteProduct(IDTextBox.Text)
ProductTableAdapter.Fill(MyDS.product)
ProductTableAdapter.Dispose()
Next
Note : gridview.rows.clear() + gridview.ds = nothing , i tried that butgridview.rows.clear() doesn't work and gridview.ds = nothing just clear the gridview and is not deleting data from access database.
You can use either of below options:
Using DataTable
Using DataGridView
Using BindingSource
The logic of all solutions is removing the rows and then updating the table adapter.
Using DataTable
You can find each rows in the data table and delete it, then update the table adapter:
For Each row As DataRow In Me.TestDBDataSet.TestTable.Rows
row.Delete()
Next
Me.TestTableTableAdapter.Update(TestDBDataSet.TestTable)
Using DataGridView
For Each row As DataGridViewRow In Me.TestTableDataGridView.Rows
DirectCast(row.DataBoundItem, DataRowView).Delete()
Next
Me.TestTableTableAdapter.Update(TestDBDataSet.TestTable)
Using BindingSource
For Each item As Object In TestTableBindingSource
TestTableBindingSource.Remove(item)
Next
Me.TestTableTableAdapter.Update(TestDBDataSet.TestTable)

Detect rows in DataGridView whose cell values have been changed by user

I have a VB.NET WinForms project that I'm building in VS2013. In a DataGridView bound to a DataSet I want to highlight each row that the user has changed - and if the user changes a row's contents back to its original values (as compared to the database values) I want to remove the highlighting.
I have been Googling for a while now and really haven't gotten anywhere.
All I know at this point is that EmployeesDataSet.HasChanges(DataRowState.Modified) returns False in the CellValueChanged event after having changed text in a cell and clicked out of the row.
My assumption is that the overall method would be something like on KeyUp event compare the current row's cell values to the DataSet (or BindingSource or TableAdapter?) and if anything is different, highlight the row, otherwise set the row to the default backcolor.
But if that's the right approach I don't understand what I would compare the row's contents to. Would it be the DataSet? The TableAdapter? The BindingSource? If it's one of those, how to I compare the correct row?
UPDATE
Some more research has made some progress:
I found this iteration code:
Dim dsChanged As DataSet = EmployeesDataSet.GetChanges()
For Each dt As DataTable In dsChanged.Tables
For Each row As DataRow In dt.Rows
For i As Integer = 0 To dt.Columns.Count - 1
Dim currentBackColor As System.Drawing.Color = dgvEmployees.AlternatingRowsDefaultCellStyle.BackColor
If Not row(i, DataRowVersion.Current).Equals(row(i, DataRowVersion.Original)) Then
dgvEmployees.Rows(dt.Rows.IndexOf(row)).DefaultCellStyle.BackColor = Color.LightPink
Else
' No changes so set it to its original color
dgvEmployees.Rows(dt.Rows.IndexOf(row)).DefaultCellStyle.BackColor = currentBackColor
End If
Next
Next
Next
I put this in a separate Sub, which is being called in the DataGridView.CellValueChanged event.
That correctly detects the rows that have changed cell values, but my code to color the background isn't quite right. As is, it is coloring each successive row from top to bottom as I make changes - regardless of what row in the DGV I edit.
I assumed that dt.Rows.IndexOf(row) would correctly get the correct index of the DGV, since I'm iterating through the DGV's DataTable.
Well, if you go hunting long enough and spend enough time trying different things, you'll eventually find an answer...
Here's the working code I ended up with:
Private Sub dgvEmployees_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles dgvEmployees.CellValueChanged
' Pass the row and cell indexes to the method so we can change the color of the correct row
CompareDgvToDataSource(e.RowIndex, e.ColumnIndex)
End Sub
Private Sub CompareDgvToDataSource(ByVal rowIndex As Integer, ByVal columnIndex As Integer)
If Not dgvEmployees Is Nothing And dgvEmployees.Rows.Count > 0 Then
' Condition required because this Method is also called when the DGV is being built and populated
Console.WriteLine("rowIndex: " & rowIndex.ToString() & ", columnIndex: " & columnIndex.ToString() & ", cell value: " & dgvEmployees.Rows(rowIndex).Cells(columnIndex).Value.ToString())
End If
' Force ending Edit mode so the last edited value is committed
EmployeesBindingSource.EndEdit()
Dim dsChanged As DataSet = EmployeesDataSet.GetChanges()
If Not dsChanged Is Nothing Then
For Each dt As DataTable In dsChanged.Tables
For Each row As DataRow In dt.Rows
For i As Integer = 0 To dt.Columns.Count - 1
If Not row(i, DataRowVersion.Current).Equals(row(i, DataRowVersion.Original)) Then
Console.WriteLine("Row index: " & dt.Rows.IndexOf(row))
dgvEmployees.Rows(rowIndex).DefaultCellStyle.BackColor = Color.LightPink
End If
Next
Next
Next
End If
End Sub
A couple of notes:
Without calling EndEdit() on the BindingSource the changes won't be detected since this is being called by the CellValueChanged, which happens before the BindingSource is changed.
I tried adding an Else clause to set the BackColor to the original color (for when the DGV row is detected to be the same as the DataSet's row or when validation fails), but I can't figure out how to account for the DGV.AlternatingRowsDefaultCellStyle.BackColor property being set. Ideas???
I think this could be improved by, since I have the row and column indexes in the Method, just going directly to the DataSet's/DataTable's corresponding row and comparing just that, instead of iterating through the entire DataSet. Ideas on that one would be appreciated, but I'll do some more testing to see if I can get it (I figured it out myself this far...)

my program is not adding items to listbox and is freezing up

im trying to add a very large amount of items to list box and what i need it for is i'm using to add selected items to itextsharp table report im using filters in the table just to display either the sales person who handled the customer or the date at which the incident occurred (or Issue was reported with the product) my filter system is as follows i have 4 categories which is 4 listboxes customer name, customer code(named listBox1 i have not got around to changing it yet) species name, and the error type my filter is placed under the searchBtn_Click event my filter and item adding code is as follows:
Private Sub searchBtn_Click(sender As Object, e As EventArgs) Handles searchBtn.Click
For Each obj As contactObject In custList
For Each item As speciesObject In speciesList
'loadLists()
If Trim(fromDate.Value) < Trim(obj.eventDate) Then
If Trim(toDate.Value) > Trim(obj.eventDate) Then
If Trim(fromDate.Value) < Trim(item.compDate) Then
If Trim(toDate.Value) > Trim(item.compDate) Then
End If
If Not customerListBox.Items.Contains(obj.customerName) Then
customerListBox.Items.Add(obj.customerName)
End If
If Not ListBox1.Items.Contains(obj.customer) Then
ListBox1.Items.Add(obj.customer)
End If
If Not speciesListBox.Items.Contains(item.name) Then
If ListBox1.Items.Contains(item.customerCode) Then
speciesListBox.Items.Add(Trim(item.name).ToUpper)
End If
End If
If Not errorListBox.Items.Contains(obj.issue + " - " + obj.issueDescription) Then
errorListBox.Items.Add(Trim(obj.issue + " - " + obj.issueDescription).ToUpper)
End If
End If
End If
End If
Next
Next
countErrors()
End Sub
then i have the query which is set up to get the customer info from the database system
Dim SqlText As String = "SELECT DISTINCT QEE.[EventID] ,QEE.[EventDate] ,QEE.[Employee] ,QEE.[Communication] ,QEE.[OtherCommunication] ,QEE.[Issue] ,QEE.[IssueDescription] ,QEE.[IssueComments] ,QEE.[Resolution] ,QEE.[ResolutionComments] ,QEE.[SalesOrderNumber] ,QEE.[CustomerPO] ,QEE.[SOStatus] ,QEE.[Customer] ,QEE.[CustomerName] ,QEE.[SalesPersonName] ,QEE.[IsResolved] ,QEE.[IssueValue] ,QEE.[DateAndTimeAdded] ,DATEDIFF(day, SOR.ReqShipDate, QEE.[EventDate]) AS Elapsed, SOR.ReqShipDate FROM [QualityTracking].[dbo].[tblQualityEventEntry] QEE INNER JOIN SysproCompanyC.dbo.SorMaster SOR ON QEE.SalesOrderNumber = SOR.SalesOrder COLLATE Latin1_General_CI_AS ORDER BY EventDate ASC, CustomerName ASC, SalesOrderNumber ASC;"
I could not fit all code on here
if you could also just general things to help as well i am new to vb.net but for other information things i have tried :
*listbox.startUpdate/endUpdate
*changing querys
*changing the sorted property (Right now its set for false)
*the issue happens when i choose select all and then hit search the database is holding almost 2Mil items and i need to be able to get it to move once i get it work stop freezing i will be able to increase the speed i just cant figure out totally where the issue is i know the query could be better probably (if you have any suggestions please feel free i'm learning)
*but i also see alot of people having this issue with listbox as being kinda a broken down way of listing items
*i have tried researching it and people have said use something else i cant do that for listbox is committed
Assuming Windows Forms.
You program might not be responding because of too many records to add, and each time you add an item into the ListBox.Items collection, the UI is refreshed.
You may either SuspendLayout while adding the lines into your Listbox, and ResumeLayout afterwards.
Private Sub searchBtn_Click(ByVal sender As Object, ByVal e As EventArgs)
customerListBox.SuspendLayout();
// Place your code to populate the ListBox control here...
customerListBox.ResumeLayout();
End sub
This shall avoid a lot of refreshes from occuring while adding the items one by one and allow the application to lighten the add of items, then you resume the layout so that it refreshes the controls to display adequate information to the screen.
OR
You may use the ListBox.Items.AddRange() method along with List.ToArray().
Private Sub searchBtn_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim custList As List(Of ConstactObject) = loadYourCustomers();
customerListBox.Items.AddRange(custList.ToArray());
Dim speciesList As List(Of SpeciesObject) = loadYourSpecies();
speciesListBox.Items.AddRange(speciesList.ToArray());
End sub
OR ELSE
I recommend using a DataGridView and setting its DataSource property to your list of objects.
So, in order to have the correct data, you'll have to:
Drop two DataGridView on your Form
Rename both DataGridView to a meaningful name (e.g. custListDataGridView, speciesListDataGridview)
Drop two BindingSource on your Form
Rename both BindingSource to a meaningful name (e.g. custListBindingSource, speciesListBindingSource)
In the designer, set the DataGridView.DataSource property to your respective BindingSource (e.g. custListDataGridview.DataSource = custListBindingsource, speciesListDataGridView.DataSource = speciesListBindingSource)
In the backing code, that is, in your searchBtn.Click event, you may set both your binding sources DataSource property
Private Sub searchBtn_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim custList As IList(Of ContactObject) = loadYourContactObjects();
custListBindingSource.DataSource = custList;
Dim speciesList As IList(Of SpeciesObject) = loadYourSpeciesObject();
speciesListBindingSource.DataSource = speciesList;
End Sub
And your information data should be listed automatically without you having to manually add each record.