Solved

WPF ListBox SelectedIndex issue

Posted on 2016-07-27
12
50 Views
Last Modified: 2016-08-05
I am setting the selected index of a bound listbox in my code behind in response to some processing that has happened. I can trace the code through and it is only setting the selected index once, the changed event for the selected index fires twice, the first time it is the value my code sets it to and the second time it is -1.

Since the code to do this is through a mixture of several objects it is hard to post an example here. Perhaps someone can give me a clue of how to debug this, or suggest why the selection I make is apparently getting reset by the listbox.

Thanks,
Sid
0
Comment
Question by:Sid Price
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 5
12 Comments
 
LVL 34

Expert Comment

by:sarabande
ID: 41733082
the first time it is the value my code sets it to and the second time it is -1.
what do you mean by 'bounded' listbox?

if somewhere a selection of -1 index is made, the listbox has no selection. after this, you could set the selection again.

so you could do the following:

instead of setting the selected index in the first case, you only save the index to select in a member variable or some other shared variable. when the change event with -1 was occuring you now set the selected index. be aware that the event was fired again after this.

if you want to find out which statement was causing the reset of the listbox you may add a static control to your form. in your code now write log messages to the static control at points where you think the listbox might get changed. if the -1 was selected, you break in the debugger and can see from the current log message which statement may have issued the reset of the listbox. you also can see into the stack where you should see perhaps which messages have been processed before. perhaps you have to add further log messages (or use a listbox for the messages) to narrow down the crucial code sequence..

Sara
0
 

Author Comment

by:Sid Price
ID: 41733093
Hello Sara,

I mean the listbox is data-bound to a Collection:

		listCues.ItemsSource = theCueList
		listCues.DisplayMemberPath = "DisplayLine"
		Dim sortDecsription As New SortDescription("ID", ListSortDirection.Ascending)
		listCues.Items.SortDescriptions.Add(sortDecsription)

Open in new window


instead of setting the selected index in the first case ...

If my code does not set the selected index the change to -1 does not happen so your suggested work-around cannot be used.

if you want to find out which statement  ...

I have used the debugger to stop when the "selected index changed" event occurs, looking at the call stack does not show where the "-1" coming from. It appears that the -1 gets set very quickly after I see the right value gets set and the code has not returned to my code before the -1 is set.

This is very confusing, thanks for helping,
Sid
0
 

Author Comment

by:Sid Price
ID: 41733176
Sara,
I am not sure if this helps but I made a DebugView log of the issue. First a short description of the path to selecting the list item.

My "Sequencer" class detects that a change of selection is required and it raises an event to request this is done. The "PlayManager" class catches this event and in turn raises an event to request the the listbox item selection. In the "MainWindow this last event is processed and the listbox selection is made. I added messaging before and after each "RaiseEvent", plus in the "MainWindow" processing of the selection:

[5240] Sequencer::SequenceFromThisCue (Before event) - selected cue 3 
[5240] PlayManager::HandleSelectThisCue (Before event) - selected cue 3 
[5240] MainWindow::HandleSelectThisCue (Entry) - selected cue 3 
[5240] MainWindow::HandleSelectThisCue - selected cue index2 Calling listCues.SelectedIndex = cueIndex 
[5240] MainWindow::listCues_SelectionChanged - selected index 2 
[5240] MainWindow::HandleSelectThisCue - selected cue index2 After listCues.SelectedIndex = cueIndex 
[5240] MainWindow::HandleSelectThisCue (Exit) - selected cue 3 
[5240] PlayManager::HandleSelectThisCue (After event) - selected cue 3 
[5240] MainWindow::listCues_SelectionChanged - selected index -1 
[5240] Sequencer::SequenceFromThisCue (After event) - selected cue 3 

Open in new window


The only place in my project that the selected index is changed is in "MainWindow" class and as you can see that method is only called once and with the correct selection.

Note that the "SelectionChanged" event is happening twice, once when I select the item requested and once to -1 so some reason.

I hope this helps understand what I am seeing.
Thanks again,
Sid
0
Salesforce Made Easy to Use

On-screen guidance at the moment of need enables you & your employees to focus on the core, you can now boost your adoption rates swiftly and simply with one easy tool.

 
LVL 34

Expert Comment

by:sarabande
ID: 41733259
MainWindow::listCues_SelectionChanged - selected index -1
could it be that it happened cause the data were reloaded from database? do you have any Code which makes the bound control 'dirty'?

If my code does not set the selected index the change to -1 does not happen so your suggested work-around cannot be used.
you could set the selected index a second time when -1 was selected ... that is not nice but might work.

Sara
0
 

Author Comment

by:Sid Price
ID: 41733357
could it be that it happened cause the data were reloaded ...

No the Collection is loaded once on startup from a file.

you could set the selected index a second time ...

Well this is a pretty awful hack but at least I can move forward with my design while I continue to try to find the real solution. Here's what I added to the changed event:

	Private useThis As Integer
	Private Sub listCues_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles listCues.SelectionChanged
		Dim iIndex As Integer = listCues.SelectedIndex
		If iIndex = -1 Then
			listCues.SelectedIndex = useThis
		Else
			useThis = iIndex
		End If
		Debug.WriteLine("MainWindow::listCues_SelectionChanged - selected index " & iIndex)
	End Sub

Open in new window


Any further ideas on the real problem here would be much appreciated,
Sid
0
 
LVL 34

Expert Comment

by:sarabande
ID: 41733447
ok. if we take for granted that your first selection also is the trigger for the reset, you first should guarantee that

   - the select is the last statement operating at the listbox in the function
     MainWindow::HandleSelectThisCue

  - that the handler MainWindow::listCues_SelectionChanged  does nothing for this case

  - and returns 'Event successfully handled' if that is possible.

Sara
0
 

Author Comment

by:Sid Price
ID: 41733481
the select is the last statement operating  ...

Here is the full code of MainWindow::HandleSelectThisCue:

	Private Sub HandleSelectThisCue(ByVal sender As Object, ByRef thisCue As Cue) Handles mPlayManger.SelectThisCue
		If theCueList.Contains(thisCue) = True Then
			Dim cueIndex As UInt32 = theCueList.IndexOf(thisCue)
			listCues.SelectedIndex = cueIndex
		End If
	End Sub

Open in new window


that the handler MainWindow::listCues_SelectionChanged  does nothing for this case

Not sure what this means, I posted the full code of MainWindow::listCues_SelectionChanged previously.

and returns 'Event successfully handled' if that is possible

The events are "Sub" methods so there is no return value.

Sid
0
 
LVL 34

Assisted Solution

by:sarabande
sarabande earned 500 total points
ID: 41733556
that the handler MainWindow::listCues_SelectionChanged  does nothing for this case
should mean that no further action was issued from this handler in this case. that seems to be the case if 'useThis' is only a helper.

The events are "Sub" methods so there is no return value.
native winapi allows to stop a cascade of windows messages by returning 'successfully handled'.

listCues.SelectedIndex = cueIndex
how do you guarantee that an index valid for theCueList also is valid for listCues ?

what is the relation between theCueList and listCues?

can you post all functions where  listCues was used somehow?

Sara
0
 

Author Comment

by:Sid Price
ID: 41733581
native winapi allows to stop a cascade of windows messages ...

This is a vb.net/WPF application, one cannot have return values on events.

how do you guarantee that an index valid for theCueList also is valid for listCues ?

The listbox is sorted by the Cue identity and these are always ascending in the input file that is read into the Collection.

can you post all functions where  listCues was used somehow?

	Private Sub MainWindow_Initialized(sender As Object, e As EventArgs) Handles Me.Initialized
		'
		' Test the cues loading
		'
		theCueList.Load("C:\DataRoot\Projects\cueassistv2.0\CueAssistv2.0\CueAssistv2.0\Shows\AvianAmb_001.aap")
		mPlayManger.CueList = theCueList
		listCues.ItemsSource = theCueList
		listCues.DisplayMemberPath = "DisplayLine"
		Dim sortDecsription As New SortDescription("ID", ListSortDirection.Ascending)
		listCues.Items.SortDescriptions.Add(sortDecsription)
	End Sub

	Private Sub btnPlaySelected_Click(sender As Object, e As RoutedEventArgs) Handles btnPlaySelected.Click
		If listCues.SelectedIndex <> -1 Then
			Dim oCue As Cue = listCues.Items(listCues.SelectedIndex)
			mPlayManger.PlayFromThis(oCue)
		End If
	End Sub

	Private Sub HandleSelectThisCue(ByVal sender As Object, ByRef thisCue As Cue) Handles mPlayManger.SelectThisCue
		If theCueList.Contains(thisCue) = True Then
			Dim cueIndex As UInt32 = theCueList.IndexOf(thisCue)
			listCues.SelectedIndex = cueIndex
		End If
	End Sub

	Private Sub listCues_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles listCues.SelectionChanged
		Dim iIndex As Integer = listCues.SelectedIndex
		If iIndex = -1 Then
			listCues.SelectedIndex = useThis
		Else
			useThis = iIndex
		End If
	End Sub

Open in new window

0
 

Accepted Solution

by:
Sid Price earned 0 total points
ID: 41736781
Sara,
Just a short note to let you know that I have resolved the issue you were kindly trying to assist with. I ended up data binding the "SelectedIndex" property of the listbox to a "CurrentIndex" property on the object that manages the collection. Initially I left the "work-around" code in that you suggested, however later when I set a breakpoint in that method the "correction" code that ran when the index was -1 was never getting executed. I have removed that work-around and the data binding continues to work.
Thanks for trying to help, it is much appreciated.
Sid
0
 

Author Closing Comment

by:Sid Price
ID: 41743967
I came to the fix through my own research and work.
0
 
LVL 34

Expert Comment

by:sarabande
ID: 41744017
Congratulations. It is great that you found a good solution and could remove the hack.

Sara
0

Featured Post

Online Training Solution

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action. Forget about retraining and skyrocket knowledge retention rates.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This document covers how to connect to SQL Server and browse its contents.  It is meant for those new to Visual Studio and/or working with Microsoft SQL Server.  It is not a guide to building SQL Server database connections in your code.  This is mo…
Wouldn’t it be nice if you could test whether an element is contained in an array by using a Contains method just like the one available on List objects? Wouldn’t it be good if you could write code like this? (CODE) In .NET 3.5, this is possible…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…
How to Install VMware Tools in Red Hat Enterprise Linux 6.4 (RHEL 6.4) Step-by-Step Tutorial

730 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question