I have created a list box and at the moment I am trying to make it such that you can delete one item or multiple items using this code:
Private Sub Delbtn_Click(ByVal sender As Object,
ByVal e As System.EventArgs) Handles Delbtn.Click
lstCountries.Items.Remove(lstCountries.SelectedItem)
lstCountries.Items.Remove(lstCountries.SelectedItems)
End Sub
However when using this I am not able to delete more than one selection at a time. What is the best way to make it so that I can delete one or more than one selection?
First, make sure there are some things selected:
If lstCountries.SelectedItems.Count > 0 Then
' MUST loop backwards thru collections when removing
' or you will remove the wrong things, miss stuff and
' run out early
For n As Integer = lstCountries.SelectedItems.Count - 1 To 0 Step -1
' remove the current selected item from items
lstCountries.Items.Remove(lstCountries.SelectedItems(n))
Next n
End if
There is also a SelectedIndicies Collection which would return a collection of integers of the items. If you iterate that, use .RemoveAt() but you still need to loop backwards.
Related
I have a form with combo boxes (cmbPort#) to select up to 8 serial ports. I want to first clear the item list for each, populate them with currently available system ports, and then add the option "Off" to each list. Finally, to set each combo box according to defaults saved in string spName(). I created a GroupBox (gBox1) and dragged each cmbPort onto it but I'm not sure how to reference the controls on it. I'm using VB 2015.
Can you help with VB.NET code to use loops ("For Each" or similar) to do this more efficiently?
Private Sub frmProp_Load(sender As Object, e As EventArgs) Handles MyBase.Load
cmbPort1.Items.Clear()
...
cmbPort8.Items.Clear()
For Each sp As String In My.Computer.Ports.SerialPortNames
cmbPort1.Items.Add(sp)
...
cmbPort8.Items.Add(sp)
Next
cmbPort1.Items.Add("Off")
...
cmbPort8.Items.Add("Off")
cmbPort1.Text = spName(1)
...
cmbPort8.Text = spName(8)
End Sub
Loops are an incredibly useful tool to master. I pitched here some code so you can get the idea, but I was working out of IDE so you might have to apply some fixes to this code to make it work as you want it to.
The main idea is that you shouldn't have to write a line more than once. If you multiply the same operation on several lines of code, you create potential problems for the future. Loops and subs are really helpful to prevent this kind of issues.
Private Sub frmProp_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'This is for later
Dim cmbIndex As Integer = 1
'You basically do the same operations for every Combobox in your list, son only one loop needed
For Each cmbPort As ComboBox In {cmbPort1, cmbPort2, cmbPort3 [...] cmbPort8} 'this is a way to declare an array
'Clear
cmbPort.Items.Clear()
'Add SerialPortNames
For Each sp As String In My.Computer.Ports.SerialPortNames
cmbPort.Items.Add(sp)
Next
'Add "Off"
cmbPort.Items.Add("Off")
'This last one is a little bit trickier because you want to match numbers
'This is the place where you get errors when something doesn't go as planned
'If you need to keep it inside the loop here's a way to achieve that, but honestly I would't do that
'Instead I would suggest that you take this part out of the loop and do it manually
If spName(cmbIndex) IsNot Nothing Then cmbPort.Text = spName(cmbIndex)
cmbIndex += 1
Next
End Sub
You shouldn't consider efficiency into this equation, as this operation will not be called all the time, only on load. I mean: you should always do things in the best way you can, but optimization is sometimes the enemy of good, readable code.
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
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
I'm working on a program called "Smart Search". In the "customize search" form,
I made it possible to delete items. Well, the problem here is that it's two listboxes. One for what you should search for and one for what happens when you search: https://i.imgur.com/aGZRoeX.png
Oh, and btw. When you select an item in one of the listbox, the same selectedindex will be selected in the other.
But when I delete the last item(s) in the list I get a error.
I think it's something wrong with my code but I can't find anything wrong with it.
The code: http://pastebin.com/LRBfx5DL
Try something like this:
Private Sub rembtn1_Click(sender As Object, e As EventArgs) Handles rembtn1.Click
Dim index As Integer = ListBox1.SelectedIndex
If index <> -1 Then
ListBox1.Items.RemoveAt(index)
If index < ListBox2.Items.Count Then
ListBox2.Items.RemoveAt(index)
End If
save()
End If
End Sub
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.