There are examples here on Stackflow on how to add ListBox items to the session and then repopulate the items back to the ListBox but for some reason it is not working.
Here's the code snippet
Private Sub btnSelect_Click(sender As Object, e As EventArgs) Handles btnSelect.Click
If lstFields.SelectedIndex >= 0 Then
For i As Integer = 0 To lstFields.Items.Count - 1
If lstFields.Items(i).Selected Then
If Not arrayFields.Contains(lstFields.Items(i)) Then
arrayFields.Add(lstFields.Items(i))
Session("items") = arrayFields
End If
End If
Next
For i As Integer = 0 To arrayFields.Count - 1
If Not lstSelected.Items.Contains((CType(arrayFields(i), ListItem))) Then
lstSelected.Items.Add((CType(arrayFields(i), ListItem)))
End If
lstFields.Items.Remove((CType(arrayFields(i), ListItem)))
Next
lstSelected.SelectedIndex = -1
End Sub
When I try to repopulate the items back to ListBox using the For Each loop, the error I kept getting using VS 2015 that shows:
An exception of type 'System.InvalidCastException' occurred in FocusVB.dll but was not handled in user code
Additional information: Unable to cast object of type 'System.Web.UI.WebControls.ListBox' to type 'System.Collections.IEnumerable'.
Here's the snippet of the for each loop:
For Each item As ListItem In Session("item")
lstSelected.Items.Add(New ListItem(item.Text, item.Value))
Next
Am I missing somewhere in the code?
Just remove ListItem from the line For each item as listitem ..
For Each item In Session("item")
lstSelected.Items.Add(New ListItem(item.Text, item.Value))
Next
Don't ask me why ,rather read this .Take a look at the namespace of it,it'll answer you(if you are not talking about System.Windows.Documents.listItem)
Your enumerated list contains Session("items") = arrayFields
However, your reference is item, not items. Change to items.
If Not Session("items") Is Nothing Then
For Each item As ListItem In Session("items")
lstSelected.Items.Add(New ListItem(item.Text, item.Value))
Next
End If
Related
It happens so often to me that I need to remove items from a List(Of) if a certain condition is met.
I prefer to do it this way:
For Each nClass As SomeClass In MyList
If (Something) Then
MyList.Remove(nClass)
End If
Next
However, when I remove an item, the collection is changed, and the For Next Statement can't proceed, and a System.InvalidOperationException is thrown.
I wonder if there's any general way to do this properly without writing big workarounds.
Can anybody tell how this should be done correctly?
I'm attaching a test code to see the error:
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim nList As New List(Of SomeClass)
For i As Integer = 0 To 5
Dim nNewItem As New SomeClass
nNewItem.Int = i
nNewItem.Text = "My text " + i.ToString
nList.Add(nNewItem)
Next
For Each nItem As SomeClass In nList
If nItem.Int > 1 And nItem.Int < 5 Then
nList.Remove(nItem)
End If
Next
End Sub
End Class
Public Class SomeClass
Private _iInt As Integer = 0
Private _sText As String = String.Empty
Public Property Int() As Integer
Get
Return _iInt
End Get
Set(value As Integer)
_iInt = value
End Set
End Property
Public Property Text() As String
Get
Return _sText
End Get
Set(value As String)
_sText = value
End Set
End Property
End Class
As Plutonix said, you need to work backwards through your loop -
Change
For Each nItem As SomeClass In nList
If nItem.Int > 1 And nItem.Int < 5 Then
nList.Remove(nItem)
End If
Next
to
For I As Integer = nList.Count to 0 Step -1
If nlist(I).Int > 1 And nList(I).Int < 5 Then
nList.RemoveAt(I)
End If
Next
The reason being that in a For Each..Next loop, the number of items in the object is recorded at the start of the loop and does not change. Even if you add or remove items in the object.
For example. Say you start off with a list of 10 letters.
A
B
C
D
E
F
G
H
I
J
So. At the start of your For Each loop, the number of items is recorded (10). As the loop iterates through the list, let's say you remove "E".
For the purpose of this explanation is doesn't matter too much which one. Anyway, you'll end up with all the subsequent items being moved back one. So what was at index position 5 will be at position 4 and so on to what was at index 10 is now at index 9 . The loop carries on and when it tries to access the item at index 10, it doesn't exist because it's outside the bounds of the list that now has 9 items.
If instead you use a `For..Next' loop stepping backwards, and start at the list item and head backwards, when you get to say, "E" and want to remove it, and then step backwards again and again until you get to the first item,the first item is still at the same index position, so no problem.
I know that a null reference exception generally occurs when accessing an item in a collection that doesn't exist. However, in this case, one is being thrown despite me explicitly creating this item mere lines beforehand. I have scoured my code and cannot find the source of this error (the code is very basic ATM as I have just begun the process of restructuring a solution made for a client.
Background info:
PhotoJobs is a custom class that holds all of the properties of a specific manufacturing Job
These are all held in a Public Dictionary(of string, PhotoJob) which is held in the MainForm class.
A ("temp") photojob is created within this dictionary to handle the addition of new jobs as data is added (this appears to be the source of the error.
Code:
Private Sub AddJob_Load(sender As Object, e As EventArgs) Handles MyBase.Load
MainForm.photoJobs.Add("temp", New PhotoJob())
pctBox.AllowDrop = True
End Sub
Public Sub pctbox_drop(sender As Object, e As DragEventArgs) Handles pctBox.DragDrop
Dim pics As String() = CType(e.Data.GetData(DataFormats.FileDrop), String()) 'Gets the data from the file drop
If MainForm.photoJobs("temp").imageList.Count = 0 Then
MainForm.photoJobs("temp").imageList = pics.ToList 'Gets the data from the file drop
Else
For i = 0 To MainForm.photoJobs("temp").imageList.Count - 1
If Not MainForm.photoJobs("temp").imageList.Contains(pics(i)) Then
MainForm.photoJobs("temp").imageList.Add(pics(i))
End If
Next
End If
MainForm.photoJobs("temp").photoID = CType(formatID(MainForm.photoJobs("temp").imageList(0)), String)
txtPhotoID.Text = MainForm.photoJobs("temp").photoID
Select Case MainForm.photoJobs("temp").imageList.Count
Case 0
MsgBox("Please ensure that you are dropping image files")
Case 1
lblImageNumber.Text = txtPhotoID.Text
checkBoxes(0)
Case 2
txtPhotoID.Text = txtPhotoID.Text & "(2)"
lblImageNumber.Text = txtPhotoID.Text
checkBoxes(1)
Case 3
txtPhotoID.Text = txtPhotoID.Text & "(3)"
lblImageNumber.Text = txtPhotoID.Text
checkBoxes(2)
Case 4
txtPhotoID.Text = txtPhotoID.Text & "(4)"
lblImageNumber.Text = txtPhotoID.Text
checkBoxes(3)
End Select
spinCounter.Value = 1
spinCounter.Minimum = 1
spinCounter.Maximum = MainForm.photoJobs("temp").imageList.Count
pctBox.ImageLocation = MainForm.photoJobs("temp").imageList(0)
End Sub
The error gets called on the If MainForm.photoJobs("temp").imageList.Count = 0 Then line.
On a second, minor note, is it fairly typical for clients to ask for "just one more little thing" that results in you having to make a major overhaul to an application, or have I just got unlucky? (slightly rhetorical)
Ensure that imageList is not null, as you declare a new PhotoJob but don't set any values in it.
When dealing with a NullReferenceException, you're not looking at something missing from a collection, it means you tried to access a member of a object which is null. This can sometimes be a side effect of an item not in a collection, if that collection returns null, but if a value does not exist in a Dictionary, you get a KeyNotFoundException
Please make sure that 'imageList' has 'count' property more than 0. Means just check that the list does have elements in it by executing theses lines before executing loop.
Dim pics As String() =CType(e.Data.GetData(DataFormats.FileDrop),String())
If MainForm.photoJobs("temp").imageList.Count > 0 Then
For i = 0 To MainForm.photoJobs("temp").imageList.Count - 1
If Not MainForm.photoJobs("temp").imageList.Contains(pics(i)) Then
MainForm.photoJobs("temp").imageList.Add(pics(i))
End If
Next
'Gets the data from the file drop
Else
MainForm.photoJobs("temp").imageList = pics.ToList
End If
Well this is embarrassing...
The solution was simply that I was missing new when I declared the list it used to read Public Property imageList as list(of string) can't believe I did that... Hey ho, thanks for all of your help guys.
I am making a dvd database system in windows form and trying to display the dvd's entered by a user. Then display the Title, Director and Genre in 3 separate listBoxes.
When the user enters the information through 3 separate text boxes, the information is stored in a structure I made called TDvd. This means I can call for example dvd.Title or dvd.Director. I also use the variable index to add this information to an array I made called Dvd(100) (just a random number I used to test).
Here is the code I currently have for adding the items to the ListBox:
For i = 1 To noOfAddedDvds
lstTitle.Items.Add(dvd(i).Title)
lstDirector.Items.Add(dvd(i).Director)
lstGenre.Items.Add(dvd(i).Genre)
Next
The variable NoOfDvdsAdded is just a way of keeping track of the number of dvd's the user has already entered.
I run this and enter the Title, Director and Genre, but when I try and display this information across the 3 listboxes, I get the error:
An unhandled exception of type 'System.ArgumentNullException' occurred in System.Windows.Forms.dll
Public Class Form1
Structure TDvd
Dim Title As String
Dim Director As String
Dim Genre As String
End Structure
Dim dvd(100) As TDvd
Dim index As Integer = 0
Dim noOfAddedDvds As Integer
Private Sub btnAddToDatabase_Click(sender As Object, e As EventArgs) Handles btnAddToDatabase.Click
If txtDirector.Text <> "" Or txtGenre.Text <> "" Or txtTitle.Text <> "" Then
txtTitle.Text = dvd(index).Title
txtDirector.Text = dvd(index).Director
txtGenre.Text = dvd(index).Genre
index += 1
noOfAddedDvds += 1
End If
End Sub
Private Sub btnDisplayDatabase_Click(sender As Object, e As EventArgs) Handles btnDisplayDatabase.Click
Dim i As Integer
For i = 0 To noOfAddedDvds
MessageBox.Show(index & ", " & i)
lstTitle.Items.Add(dvd(i).Title)
lstDirector.Items.Add(dvd(i).Director)
lstGenre.Items.Add(dvd(i).Genre)
MessageBox.Show(index & ", " & i)
Next
End Sub
End Class
According to the documentation, an ArgumentNullException is thrown by the Add() method if the argument passed to it is null. (Or Nothing in VB.) So one of these is Nothing at runtime:
dvd(i).Title
dvd(i).Director
dvd(i).Genre
You'll have to debug to determine which. It would seem that the error is because you're starting your iteration at 1 instead of 0, I would think it should be:
For i = 0 To noOfAddedDvds - 1
So when you get to the index of noOfAddedDvds in your collection, that element will be an uninitialized struct with Nothing strings.
You'll definitely want to fix the iteration (indexes start at 0). Additionally, you may also benefit from initializing the String properties in your struct to String.Empty internally. Depends on whether you want similar errors to manifest as an exception or as an empty record. Sometimes the latter makes the problem more obvious since at runtime you'd see that your output started on the second record.
Just a few pointers...
The Items collection on the ListBox is actually 0 indexed, by which I mean that instead of going "1,2,3", it actually goes (0,1,2).
That's what your problem is.
Hint - think about perhaps using a List instead of an array as well... (for dvd)
Your thing cries out for being rewritten in OO form:
Friend DVDGenres
Undefined
Comedy
Action
Adventure
Sci-Fi
End Enum
Friend Class DVD
Public Property Title As String
Public Property Director As String
Public Property Genre As DVDGenres
Public Sub New
Title = ""
Director = ""
Genre = DVDGenres.Undefined
' other stuff too
End Sub
Public Overrides Function ToString As String
Return Title
End Sub
End Class
Now something to store them in. Arrays went out with Rubik's Cubes, so a List:
Private myDVDs As New List(of DVD)
A list and a class can do what arrays and structures can without the headaches. Add a DVD:
Dim d As New DVD
d.Name = TextBoxName.Text
d.Director = TextBoxDir.Text
d.Genre = comboboxGenre.SelectedItem
' add to the container:
myDVDs.Add(d)
Display all the DVDs in a ListBox to pick from:
AllDVDsLB.DataSource = myDVDs
AllDVDsLB.DisplayMember = "Title"
This will set your list as the datasource for the listbox. Whatever is in the List is automatically displayed without copying data into the Items collection. Then, say from selectedindex changed event, display the selected item details to some labels:
Label1.Text = Ctype(AllDVDsLB.SelectedItem, DVD).Title
Label2.Text = Ctype(AllDVDsLB.SelectedItem, DVD).Director
Label3.Text = Ctype(AllDVDsLB.SelectedItem, DVD).Genre.ToString
Iterate to do something like what is in the Question:
For Each d As DVD in myDVDs ' CANT run out of data
lstTitle.Items.Add(d.Title)
lstDirector.Items.Add(d.Director)
lstGenre.Items.Add(d.Genre.ToString)
Next
Or iterate and reference with an Int32:
For n As Integer = 0 To myDVDs.Count - 1
lstTitle.Items.Add(myDVDs(n).Title)
' etc
Next n
HTH
I have an issue with my code; and would appreciate some assistance getting her to do what I want without an annoying error. Read the databound listbox strings, find the user selected string and write said string to a file.
Private Sub btnContinue_Click(sender As System.Object, e
As System.EventArgs) Handles btnContinue.Click
' 1st file and mySQL Update to testing table
If txtLocation.Text.ToString <> "" And txtUnitTested.Text.ToString <> "" Then
Dim filewriter As New System.IO.StreamWriter(
"C:\Users\OER\Documents\Visual Studio 2010\Projects\frmTest1_0.txt")
Dim curItem = lstCustomer.SelectedItem
Dim now As DateTime = DateTime.Now
With filewriter
.WriteLine(vbCrLf + (now.ToString("F"))) ' Write the DateTime to the file
End With
For Each objDataRowView As DataRowView In lstCustomer.SelectedItems
Dim item As String
For Each item As DataRowView In Me.lstCustomer.Items.Item("customer")
item = String.Parse(lstCustomer.SelectedValue)
WriteLine(curItem(item))
Next item
Next ' THIS IS THE FOR LOOP I AM HAVING ISSUES WITH!!!!!!!
With filewriter
.WriteLine(vbCrLf + txtLocation.Text + vbCrLf + txtUnitTested.Text)
End With
filewriter.Close()
frmTest1.Show()
Else
MsgBox("Please Type the Location and Unit Tested!!!", vbCritical)
txtLocation.Clear()
txtUnitTested.Clear()
txtLocation.Focus()
End If
These loops:
For Each objDataRowView As DataRowView In lstCustomer.SelectedItems
Dim item As String
For Each item As DataRowView In Me.lstCustomer.Items.Item("customer")
item = String.Parse(lstCustomer.SelectedValue)
WriteLine(curItem(item))
Next item
Next
Are going to cause you some problems. You have declared a loop variable with the same name as another variable. And then you are assigning a value to it.
Also, I am not very clear on what the purpose of the two loops are. I am somewhat confused about what you are trying to accomplish in this section of code. I would start by renaming the variable in this line:
Dim item as String
I am going to use this for an example:
Dim result as string
Make that something else, and you cannot then change the value of item (since that is the loop variable) in the loop. That will cause an error.
Changing the code inside the loop to:
result = String.Parse(lstCustomer.SelectedValue)
Odds are this still won't get you to where you are trying to go, but it is a good start. Unless each item in your lstCustomer contains multiple items to iterate through I think you probably only need that first, outer loop, anyway.
If your loop starts like this:
For Each objDataRowView As DataRowView In lstCustomer.SelectedItems
Then I think you will want:
objDataRowView.Item("customer")
as what is output. I think that will be the value of the customer field from your table.
You are basically saying that this row has a column called customer.... I would like that value please.
I need to retrieve my data from a ListView control set up in Details mode with 5 columns.
I tried using this code:
MessageBox.Show(ManageList.SelectedItems(0).Text)
And it works, but only for the first selected item (item 0). If I try this:
MessageBox.Show(ManageList.SelectedItems(2).Text)
I get this error:
InvalidArgument=Value of '2' is not valid for 'index'. Parameter name: index
I have no clue how I can fix this, any help?
Edit: Sorry, should have said, I'm using Windows.Forms :)
Right, from what I've tested:
Private Sub Button1Click(ByVal sender As Object, ByVal e As EventArgs)
For index As Integer = 0 To Me.listView1.SelectedItems.Count - 1
MessageBox.Show(Me.listView1.SelectedItems(index).Text)
Next
End Sub
(items added like this:)
For i As Integer = 0 To 99
Me.listView1.Items.Add(String.Format("test{0}", i))
Next
It just works.
So are you sure you have selected more than 1 item?
Could you please show us more code? :)