SelectedIndexChanged causes selectedindex to reset to -1?

A

Alec MacLean

Hi,

I have a couple of win forms where I am editing values that are stored in a
SQL database.

I'm using the listbox control to hold the data object each form interacts
with. Each object is defined by my own classes.

On the first form, I use an approach to reduce the number of database calls.
This essentially consists of :

1. Update the values in the database
2. Update the copy of the object currently being edited with the new values
so that is matches the values saved to the db
3. Re-insert the updated object back into the listbox at the same position.

Step 3 is achieved very simply by the following code:
Me.lbCampaigns.Items.Item(Me.CurrentCampaign.ListPos) = Me.CurrentCampaign

(The ListPos is an integer property of the object class that is set when the
item is selected from the listbox.)

The re-insertion of the object to the listbox causes the
SelectedIndexChanged event to fire (although strictly speaking we have not
moved the selection index). In my case, I handle this event and make a call
to refresh the visual control values with the updated object (this is a bit
redundant as we are not moving between selected items, but I can't prevent
the event firing). The SelectedIndex remains at the original value as per
the users selection.

Ok, so this all seems to work fine.

So, I wanted to use the same process on the second form. I implemented
another class to match the requirements of this form. This class also has a
ListPos property defined to store the SelectedIndex value.

In the same manner as on the first form, I copied the updated object
instance back into the listbox.
Me.lbQModes.Items.Item(Me.CurrentQMode.ListPos) = Me.CurrentQMode

However, for some reason, as soon as the SelectedIndexChanged event begins,
the SelectedIndex value is reset to -1, which then prevents the subsequent
procedures from being able to operate properly as they rely on being able to
identify and use a selected item.

I can find no obvious or sensible reason for why this second form should
cause a different behaviour in the SelectedIndexChanged event, so I have
resorted to making a second database call in order to totally reload the
listbox control, then loop through to find the matching ID of the item
selected and re-selecting it.

This approach seems heavy-handed to me and is especially frustrating given
that it works correctly on the first form. I have checked all properties of
the two different listboxes to see if this might have been a possible cause,
but other than name, anchor, position and size, they are using identical
property settings.

I'm at a loss to explain it - can anyone perhaps indicate where I might be
missing something? Not urgent - as I say I've used a total refresh approach
to get past it, but I would prefer the more elegant solution to work!

Thanks.
 
S

Stephany Young

First of all, you have to understand what happens when the selection in a
ListBox, (or various other controls), happens.

If you have no item selected and select an item, the SelectedIndexChanged
fires once.

If you have an item already selected and select another item, the
SelectedIndexChanged fires twice. The first time as the current item becomes
deselected and the SelectedIndex becomes -1 and the second time as the new
item becomes selected. This is easily handled by testing for SelectedIndex
= -1 or SelectedItem IsNothing in the SelectedIndexChanged event handler.

Using the ListBox, as you are, as a container for a collection of your
Campaign objects is perfectly fine but you have to remember that the that
the ListItem does not contain a Campaign object, rather it contains a
reference to your Campaign object.

Because of this there is no need to 'reinsert', as you call it, when you
update one or more properties of the Campaign object. This can easily be
confirmed by:

CurrentCampaign = CType(lbCampaigns.SelectedItem, Campaign)

CurrentCampaign.ListPos = 12345

Console.WriteLine(CType(lbCampaigns.SelectedItem,
Campaign).ListPos.ToString())

The result should be 12345 and demonstrates that CurrentCampaign and
lbCampaigns.SelectedItem both hold references to the same object without any
need to 'reinsert'.

The act of 'reinsert'ing destroys the current reference and replaces it with
a new reference to the same object. The destruction of it's current
reference is what causes the SelectedIndex to change and whether one thinks
it is intuitive or not, if you think about it, it is actually logical.
 
G

Guest

You can do a "RemoveHandler" then do your stuff then a "AddHandler". This
will prevent the events from firing while you do your thing.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top