Can't set SelectedIndex of a combo box

willisgt

Active Member
Licensed User
I've got a program that asks the user a series of questions, sort of like a survey. The answers are stored in an SQLite table.

If the user re-visits a question, I need for the previous answer to be displayed - the right radio buttons and checkboxed must be checked, text boxes filled out, and so on. All of this is working just fine except for my combo boxes.

I create the combo box at runtime via AddComboBox(). But when I try to set the SelectedIndex, it goes kablooey.

The line in the code is:

Control( iControlName ).SelectedIndex = xi

where the control is a combo box;
the combo box has had ten items added to it, so Control( iControlName ).Count = 11 (my ten items plus the 'blank' item at SelectedIndex= -1);
xi = 3.

The specific error message is:

Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index

Given that the combo box has eleven (11) items in it, how can this be happening?

As always, any and all help is greatly appreciated.

:sign0163:
 

Rioven

Active Member
Licensed User
Longtime User
Hi willisgt,

When index=-1 means no selection have been made yet, this is the blank and not included in count, When you add 10 items the Index starts 0 to 9...this counts only 10.

Regards,
 

agraham

Expert
Licensed User
Longtime User
The following code fragment succesfully does what you are appear to be trying to so there's nothing wrong in principle with what you are doing.
B4X:
Sub App_Start
   Form1.Show
   AddComboBox ("Form1", "cmb", 10, 10, 120, 30)
   For i = 1 To 10
           Control("cmb").add("fred"&i)
   Next
   xi=3
   Control("cmb").selectedindex=xi
   Msgbox("Count = " &Control("cmb").count & Chr(13) & "Selected Index = " & Control("cmb").selectedindex )
End Sub

However I cannot recreate your error by making xi an invalid number. I get a different error - "Invalid Argument. Value of '11' not valid for 'Selected Index'. Parameter name: SelectedIindex"
Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
The parameter name is a clue. I think that you may be ascribing the error to the wrong thing. "Index" is not a parameter name associated with a ComboBox as far as I can see.

Also

the combo box has had ten items added to it, so Control( iControlName ).Count = 11 (my ten items plus the 'blank' item at SelectedIndex= -1.
With ten items added Count should be 10, not 11 as shown in MessageBox in the above fragment.


EDIT :- I've managed to get the same error message as you have. This error can be caused by an out of range Index to an ArrayList.Item(Index) call. Could this be the problem in your case?
 
Last edited:

willisgt

Active Member
Licensed User
Not sure it's that...

I've double-checked my code and the contents of the iControlName string; it's

'controlPAIN01-00' (without the single quotes). So I'm not injecting quotation marks as far as I can tell.

If I add something like this on the previous line:

Msgbox( "set:" & xi & ", now:" & Control( iControlName ).SelectedIndex & " of " & Control( iControlName ).Count )

I get this:

set:5, now:-1 of 11

So I know that the string stored in iControlName is good; otherwise, it would bomb on Control( iControlName ).Count.

I also know that the value I'm trying to set (5) is within the range of values for that combo box (11). And oh, you guys are right - there are actually eleven elements. I'd said that I'd added ten, but I was wrong - I'm adding eleven.

I'm intrigued by the idea that this could have something to do with an ArrayList. I'm actually storing the values for the combo box in a companion ArrayList, but that control is referenced with Control( iArrayName), not Control( iControlName ).

So I don't see how the code I've got is producing this result.

:sign0085:
 

willisgt

Active Member
Licensed User
More complete code snippet

Here's a more complete hunk of the code that's causing my problems...

I'm including a more complete code snippet. Please forgive the multiple Msgbox calls; I was using them to hunt for answers.

---


' load previous answers

If wordsB(0) = "SELECT" Then 'its a data entry field

For xi = 0 To ( Control( iArrayName ).Count - 1 )
'Msgbox( "xi:" & xi )
'Msgbox( "c:" & Control( iArrayName ).Count )
'Msgbox( "gPrev:" & gPrevAnswer )
'Msgbox( "gPrev c:" & ArrayLen( gPrevAnswerArray()) )
'Msgbox( "xa:" & xa )
If gPrevAnswerCount > 0 AND gPrevAnswerCount > xa Then
If Control( iArrayName ).Item(xi) = gPrevAnswerArray(xa) Then
Msgbox( "set:" & xi & ", now:" & Control( iControlName ).SelectedIndex & " of " & Control( iControlName ).Count )
Msgbox( "'" & iControlName & "'" )
Control( iControlName ).SelectedIndex = xi
Control( iControlName ).Refresh
End If
End If
Next

Else If


Again, it's the "Control( iControlName ).SelectedIndex = xi" line that bombs.

:sign0085:
 

willisgt

Active Member
Licensed User
I get a different error message

I also tried adding the quotes; the error message I'm getting is:

'Object reference not set to an instance of an object'

Which, naturally, is quite different. But totally expected.

And shame on me for not mentioning this in my first post: I'm using v.5.50.

:sign0085:
 

willisgt

Active Member
Licensed User
Code emailed

Erel, thanks for taking the time to look at this. It's over 7500 lines of code, so posting it here would be impractical. I'll email it right away.

Gary
 

willisgt

Active Member
Licensed User
oh, GOOD GRIEF!

Thanks to everyone who helped me zero in on this problem. I found the cause, and thought I'd pass it on.

The combo box I've been complaining about is created at runtime. In addition to creating the box, I also added an event to catch SelectionChanged. So when I set the SelectedIndex, like so...

Control( iControlName ).SelectedIndex = xi

it raises an event that takes me into a completely different section of code. I'm still not sure why the error seems to happen on the line above, but take out the AddEvent, and everything's cool.

So it really had nothing to do with setting the SelectedIndex of a combo box. It had everything to do with me losing sight of what event-driven programming is all about.

Sorry for taking everyone's time with a bogus thread.

Gary

:sign0013:
 

willisgt

Active Member
Licensed User
Solved my own problem - and yes, this is my final answer.

Okay. At long last, the mystery has been solved. Sit down and make yourself comfortable, this takes a bit of explaining. I'll keep this simple for the new coders in the group.

My program creates most of its controls dynamically, at runtime. One of them is a combo box. Right after I create the combo box, I add an event to it to trap the SelectionChanged event.

Then I try to set the SelectedIndex of the combo box. Whoops. Crash.

Why?

Turns out that any subroutine triggered by the SelectionChanged event *must* have the Index and Value parameters. Perhaps this will explain better...

B4X:
Sub App_Start

   Form1.Show

             AddComboBox( "Form1", "cmb", 10, 10, 120, 30 )

   For i = 1 To 10
      cmb.Add( "fred" & i )
   Next

   xi = 3
   cmb.SelectedIndex = xi

   Msgbox( "Count = " & cmb.Count & Chr(13) & "Selected Index = " & cmb.SelectedIndex )
   AddEvent( "cmb", SelectionChanged, "wubba" )

End Sub


Sub wubba

   show.Text = "" & cmb.Item( cmb.SelectedIndex )

End Sub


This program won't work. But make this one little change...


B4X:
Sub wubba( Index, Value )

   show.Text = "" & cmb.Item( cmb.SelectedIndex )

End Sub


And everything's good. See why?

When the SelectedIndex of the combo box is changed, it raises a SelectionChanged event. When that event is passed to the subroutine I specified, two parameters get sent along with it - Index and Value. The subroutine has to accept those two parameters, or else bad things happen.

If you create a combo box in the forms designer, and also add an event to that combo box in the designer, the subroutine will be created for you, parameters and all. That will show you the proper way for a subroutine to handle a SelectionChanged event.

Hopefully someone will find this useful.

:sign0098:
 
Top