[Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 463
  • Last Modified:

combo.SelectedIndex...getting ArgumentOutOfRangeException


I have a class that inherits from ComboBox.  It is used on various search pages for my windows forms application.
Its datasource is a datatable, valuemember a the column "id_column", displaymember is the column "display_column".

I keep track of the last "value" (an integer gathered from the "value member" of it datasource) a user selected so that if instantiate the control again, on another form for example, I call a method I created that will reload that value.  The end product is a search control that saves and display's the last selected value it had.

It is important to mention that because it is a combo, I needed a way for a user to clear the search criteria, so I added a blank row at position 0 (the first visible value of the combo).

I get the following exception whenever I try to set the value of combo.

Specified argument was out of the range of valid values.
Parameter name: '1' is not a valid value for 'index'.

where the '1' in this case is the second row (first value) I want (first row contains a blank).

I think it may have to do with my inserting a blank first row.
Also that I'm trying to set the value before the form is actually displayed because it works if I call the method after the form is visible.

Here is some insight to my code.

'*****************************************************************************************
' instatiate search control and place on search form (called from search form contructor)
'*****************************************************************************************

Dim ctl As New SearchControl 'inherits combo

ctl.loadExistingValue
ctl.Width = 200
ctl.Location = New System.Drawing.Point(m_iXPos, m_iDynY)

Me.pnlDynaControls.Controls.Add(ctl) 'add the control to the form

'**********************************************************
' serch control constructor
'**********************************************************

Public Class SearchControl
Inherits ComboBox

Public Sub New()

    Dim oDataTable As DataTable
    Dim dataclass As MyDataClass

    dataclass = New MyDataClass
    oDataTable = MyDataClass.getData 'returns a datatable of my look values

    'add blank first row
    Dim oDataRow As DataRow
    oDataRow = oDataTable.NewRow
    oDataTable.Rows.InsertAt(oDataRow, 0)
    oDataTable.AcceptChanges() 'tried this to see if exception would go away, it did not.

    Me.DataSource = oDataTable
    Me.DisplayMember = "display_column"
    Me.ValueMember = "id_column"

    Me.DropDownStyle = ComboBoxStyle.DropDown
    Me.MaxDropDownItems = 30
End Sub

End Class


'**********************************************************
' loadExistingValue method of my search control
'**********************************************************
Public Sub loadExistingValue()


      Dim iValue As Int32
      
      iValue = previousvalue 'an integer value I save

      'don't want event to fire, so I remove the handler here
      RemoveHandler Me.SelectedIndexChanged, AddressOf SearchControl_SelectedIndexChanged


      'loop throught datasource values searching for the index of the value I have saved
      For i As Int32 = 0 To DirectCast(Me.DataSource, DataTable).Rows.Count - 1
          If Equals(DirectCast(Me.DataSource, DataTable).Rows(i)(Me.ValueMember), iValue) Then

               '********************************************
               ' EXCEPTION GETS THROWN HERE
               '********************************************
                Me.SelectedIndex = Integer.Parse(i)
               
            Exit For
          End If
      Next


      AddHandler Me.SelectedIndexChanged, AddressOf MCSSReportCombo_SelectedIndexChanged


End Sub


Any takers?
This one has baffeled me for several days now.

Thanks.
0
RickJa
Asked:
RickJa
  • 15
  • 6
  • 2
  • +1
1 Solution
 
gregoryyoungCommented:
In your command window ...

find out what value is being set for i here ...

and what

Me.Items.Count is ....

I'd be willing to bet your items .count is 0

Greg
0
 
RickJaAuthor Commented:

me.items.count = 0

but me.datasource.rows.count = 3

I thought that the "item" count is only usefull (or only matters) if you added "items" to the combo.  I assigned a datasource, value/display member.

0
 
RickJaAuthor Commented:

Oh and the value for i was correct.  It was a valid value that exists in the value member column of the combo's datasource.

Thanks.

Rick
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
gregoryyoungCommented:
nope items should still have a count ... as databinding creates the items.

Greg
0
 
RickJaAuthor Commented:

Hmmmm.
Could you point me in the right direction to find out why my items.count = 0?
0
 
gregoryyoungCommented:
Well for starters I would put a simple if statement around where you set the selectedindex and look at the behavior ...

if(Value < this.Items.Count && Value >= 0) {
}


I would also start setting breakpoints and looking where my items.count = 0.

Greg

0
 
RickJaAuthor Commented:

I put some console messages right after setting the datasource...

Me.DataSource = oDataTable
Console.WriteLine("Datasource row count: " & Me.DataSource.rows.count.ToString)
Console.WriteLine("Item Count: " & Me.Items.Count.ToString)

Me.DisplayMember = "display_column"
Me.ValueMember = "id_column"

console read.....
Datasource row count: 3
Item Count: 0

I added a watch to items.count.  It was never a value other than 0.
0
 
RickJaAuthor Commented:

I'm leaving the office for the day.  Thank you for all your help so far.  I'll check in tomorrow (maybe event tonight at home).
0
 
amyhxuCommented:
I wouldn't write a custom comboBox class to achieve the same thing. You can use the normal combobox and write subroutines in a module which can be shared within your whole program.

Just drag combobox controls to your forms where applicable. You can add a module to the project:

Module Module1

    Public g_SelectedIndexChanged_Enabled As Boolean

    Public Sub FillCombo(ByVal cb As ComboBox)

        Dim oDataTable As DataTable
        Dim dataclass As MyDataClass

        dataclass = New MyDataClass
        oDataTable = MyDataClass.getData 'returns a datatable of my look values

        'add blank first row
        Dim oDataRow As DataRow
        oDataRow = oDataTable.NewRow
        oDataTable.Rows.InsertAt(oDataRow, 0)

        cb.DataSource = oDataTable
        cb.DisplayMember = "display_column"
        cb.ValueMember = "id_column"

        cb.DropDownStyle = ComboBoxStyle.DropDown
        cb.MaxDropDownItems = 30

    End Sub

    Public Sub loadExistingValue(ByVal cb As ComboBox)

        Dim iValue As Int32
        iValue = previousvalue 'an integer value I save

        g_SelectedIndexChanged_Enabled = False

        'loop throught datasource values searching for the index of the value I have saved
        For i As Int32 = 0 To DirectCast(cb.DataSource, DataTable).Rows.Count - 1
            If DirectCast(cb.DataSource, DataTable).Rows(i)(cb.ValueMember) = iValue Then
                cb.SelectedIndex = i
                Exit For
            End If
        Next

        g_SelectedIndexChanged_Enabled = True

    End Sub

End Module


in your search form Load event:

    ctl.FillCombo(ctl)
    ctl.loadExistingValue(ctl)

in your search form ctl.SelectedIndexChanged event:

    If  g_SelectedIndexChanged_Enabled Then
        'do something
    End If

so the selectedIndexChanged event is fired, but the "do something" code won't be executed when you call ctl.loadExistingValue(), same effect as you remove and add handler.



0
 
ptakjaCommented:
I don't know if this is the source of your problem, but typically, when you inherit from another class, in the new class's constructor (or New sub) you should call the base class' New method to make sure the base class is instantiated properly:

Public Sub New()
   Call MyBase.New()

    Do your stuff here...

End Sub

Could be that the index property has been properly initialized which is why it would be zero. Just a thought...

Jeff
0
 
amyhxuCommented:
Yes, ptakja, I think that is the source of his problem. There may be more sources, but this is the one I've observed. Therefore I suggested not using inherited combobox at all just to avoid problems that can be very hard to find. Adding MyBase.New() to Sub New() may work. I just don't think there is the need of using inherited comboBox.
0
 
ptakjaCommented:
In the last line of my original post...

Could be that the index property has been properly initialized which is why it would be zero. Just a thought...

That SHOULD read:

Could be that the index property has NOT been properly initialized which is why it would be zero. Just a thought...
0
 
RickJaAuthor Commented:

I will add the mybase.new and keep you all posted.
My subclass contains more than just the posted routines, but there meir properites to maintain state and some other pertainant information.  I left all that other stuff out to make my problem a bit more "targetable".  I don't feel the other properties have much to do with my problem.  You never know though.  I may have to post the other features of my combo if mybase.new doesn't work, they may have to do with the cause.

I'll try this is out now.

0
 
RickJaAuthor Commented:


Now I'm getting the exception when the control is added to the form.
I added mybase.new to the contructor of my inherited class.
Once the control is created and loadExisting selects the value, the control is then added to the form (actually a panel on the form) using the following.

SearchForm.Panel.Controls.Add(ctl)

So the routines are logically laid out like this:
  instantiate control and load datasource (this is where I added mybase.new)
  select the prefious value that was selected (loadExistingValue method)
  add control to form (the one line of code above)

I get the same exception:
An unhandled exception of type 'System.ArgumentOutOfRangeException' occurred in system.windows.forms.dll
Additional information: Specified argument was out of the range of valid values.

Would help to mention that it only throws exception when selectedindex is called prior to form loading, I can click a button to set it once instanciated and visible and it goes right to the correct value/index.

I'm still seeing the that the datasource.rows.count = 3 and items.count = 0.

Also, when you inherit from a combo it automatically places two methods:
        Protected Overrides Sub RefreshItem(ByVal index As Integer)

        End Sub

        Protected Overrides Sub SetItemsCore(ByVal items As System.Collections.IList)

        End Sub

I normally just delete them.  Could that be cause, my not using them?
   
0
 
gregoryyoungCommented:
"Would help to mention that it only throws exception when selectedindex is called prior to form loading, I can click a button to set it once instanciated and visible and it goes right to the correct value/index."

it probably hasn't been bound yet.

If this is the case ... just put the if I mentioned above ...

Greg
0
 
RickJaAuthor Commented:

I used those two methods at the bottom of my last post (RefreshItem and SetItemsCore).
I just called the methods in the base class like this.

        Protected Overrides Sub RefreshItem(ByVal index As Integer)
            MyBase.RefreshItem(index)
        End Sub

        Protected Overrides Sub SetItemsCore(ByVal items As System.Collections.IList)
            MyBase.SetItemsCore(items)
        End Sub

And the exception is now thrown from the previous location as mentioned in my initial post.
It was the inclusion of the mybase.SetItemsCore method that changed caused the exception move from been thown at..

   SearchForm.Panel.Controls.Add(ctl)

to be thrown at...

   Me.SelectedIndex = Integer.Parse(i)

It appears to be the same exception, it is just thrown at two different locations.

Anyway, still playing with this...I hope we can get this one.

0
 
RickJaAuthor Commented:

Will try that now Greg.
Thanks
0
 
gregoryyoungCommented:
btw the selectedindex might be getting changed before the databinding has occurred.

0
 
RickJaAuthor Commented:

The "if" you mentioned above was as follows:
  if(Value < this.Items.Count && Value >= 0) {
  }


I added similar logic (see below), but used "i" instead of my iValue since it is the index I want to compare with the item count, not the value I'm looking for in the "ValueMember" of the combo's datasource.

After implementing, I not longer received the exception, but the value was never getting set because items.count is always 0.  I checked item.count in several places, even after the control is visible and it is always 0.  

Are you sure that assigning a datsource should create "items"?


     For i As Int32 = 0 To DirectCast(Me.DataSource, DataTable).Rows.Count - 1
         If Equals(DirectCast(Me.DataSource, DataTable).Rows(i)(Me.ValueMember), iValue) Then

             If Integer.Parse(i) < Me.Items.Count And Integer.Parse(i) > 0 Then
                 Me.SelectedIndex = Integer.Parse(i)
                 Exit For
             End If
             
          Exit For
         End If
     Next

0
 
RickJaAuthor Commented:

"btw the selectedindex might be getting changed before the databinding has occurred."

Do you mean I might be calling the me.selectedindex = i before the databinding has occured?

I don't know much about databinding, but will do some research.  I always use the datasource way, but I guess your saying it is all related.  

Thanks, will look into.
0
 
RickJaAuthor Commented:

I'm testing out the use of

 Me.DataBindings.Clear()
 Me.DataBindings.Add("SelectedIndex", Integer.Parse(i), "")

in place of

 Me.SelectedIndex = Integer.Parse(i)

Seems to be working better, but it is acting a little funny.
Just letting you all know.

Thanks.
0
 
RickJaAuthor Commented:

I'm stumped.
It seems to work now using the following to set the selected value/index/item of the combo.

 Me.DataBindings.Clear()
 Me.DataBindings.Add("SelectedIndex", Integer.Parse(i), "")

But it wasn't working with this code before, which is why switched to the selected index method.  I even commented out the mybase.new I added, and the two methods (SetItemsCore and RefreshItem).

And my items.count is now 3, but I'm having trouble stepping through to find out where it is actually changine.

I want to award points, but am unsure on what basis to award them.  The items.count seems to directly relate to my issue.  I would like to know exactly what is happening here.  I think it has to do with my lack of databinding knowledge and how the following differs.

combo.datasource = ...
combo.items.add(....)

combo.selectedindex = ...
combo.databindings.add("selectedIndex", i,"")

for example, what is the difference between using selectedindex = ... and databindings.add("selectedindex", i,"")?




0
 
RickJaAuthor Commented:

Could someone provide me an explaination of the difference between the following?

combo.datasource = ...
combo.items.add(....)

combo.selectedindex = ...
combo.databindings.add("selectedIndex", i,"")

for example, what is the difference between using selectedindex = ... and databindings.add("selectedindex", i,"")?

What does items.count refer to when I set the "datasource" to a datatable (the datarows??).
0
 
gregoryyoungCommented:
"for example, what is the difference between using selectedindex = ... and databindings.add("selectedindex", i,"")?"

selectedindex = fires immediatly
databindings.add(...) will not happen until databinding occurs later ...


combo.datasource = ... sets the datasource for databinding (will be bound later)
combo.items.add(....)    adds an items immediately to the items collection

Items.Count should be the same through both circumstances (ONCE the databinding has occurred) ...


does this make sense ?
0
 
RickJaAuthor Commented:

I see.
You mentioned "will not happen until databinding occurs later.."
And that "Items.Count should be the same through both circumstances (ONCE the databinding has occurred) ... "

When does databinding actually occur?
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

  • 15
  • 6
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now