views:

46

answers:

2

Hi all I have this code to check if an item from a textbox is in a listbox and its giving me the error at the bottom. Any ideas what im doing wrong? I copied it from another part of my project and it was working for that part so I cant see whats wrong.

        If LocationsSearchTextBox.Text <> "" And LocationListBox.Items.Count > 0 Then
            tempInt = 0

            While (tempInt < ClientListBox.Items.Count)
                If LocationListBox.Items(tempInt).ToString.Contains(LocationsSearchTextBox.Text) = False Then
                    LocationListBox.Items.RemoveAt(tempInt)
                End If
                tempInt += 1
            End While
        End If

System.ArgumentOutOfRangeException was unhandled Message="InvalidArgument=Value of '2' is not valid for 'index'. Parameter name: index" ParamName="index" Source="System.Windows.Forms" StackTrace: at System.Windows.Forms.ListBox.ObjectCollection.get_Item(Int32 index) at AuctioneerProject.Viewing.LocationsSearchTextBox_KeyPress(Object sender, KeyPressEventArgs e) in C:\Users\admin\Desktop\Auctioneers\AuctioneerProject\AuctioneerProject\Viewing.vb:line 301 at System.Windows.Forms.Control.OnKeyPress(KeyPressEventArgs e) at System.Windows.Forms.Control.ProcessKeyEventArgs(Message& m) at System.Windows.Forms.Control.ProcessKeyMessage(Message& m) at System.Windows.Forms.Control.WmKeyChar(Message& m) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.TextBoxBase.WndProc(Message& m) at System.Windows.Forms.TextBox.WndProc(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData) at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) at System.Windows.Forms.Application.Run(ApplicationContext context) at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun() at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel() at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine) at AuctioneerProject.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 81 at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart() InnerException:

+1  A: 

ClientListBox.Items.Count is evaluated when the loop starts. So, you might have started out with 3 or more items, but as you remove them, there will eventually be less. My guess is that by the 3rd time through the loop (you're on i = 2) that there is no longer 3 or more items in ClientListBox. So, the index is out of bounds. This is a common gotcha when you're removing items from a collection or array.

The classic way to avoid this problem is to iterate backwards. Something like:

Dim tempInt = ClientListBox.Items.Count - 1
While (tempInt > -1)
    If LocationListBox.Items(tempInt).ToString.Contains(LocationsSearchTextBox.Text) = False Then
        LocationListBox.Items.RemoveAt(tempInt)
    End If
    tempInt -= 1
End While

This has happened to everyone!

Patrick Karcher
Thats very right thanks
Shane Fagan
I did it a little differently though I just If LocationListBox.Items(tempInt).ToString.Contains(LocationsSearchTextBox.Text) = False Then LocationListBox.Items.RemoveAt(tempInt)else tempInt += 1End If
Shane Fagan
You should definitely do it that way if you're in school, because you always want to be correct but **not** do it the way they expect.
Patrick Karcher
+1  A: 

If you're going to loop over a list and sometimes remove items from the list then it's better to count "backwards".

So start with tempInt set to the maximum number of rows:

tempInt = LocationListBox.Items.Count-1

and subtract from tempInt as you loop through the list:

tempInt -=1

Of course the while loop has to be modified too, to read:

While (tempInt >= 0)
hawbsl
+1 You should have gotten an upvote too!
Patrick Karcher