|
-
Jan 29th, 2009, 08:05 PM
#1
[2005] ListView SelectedIndexChanged
I have two listviews with many items present. When the user clicks an item in ListViewA, I highlight items in ListViewB. I use the SelectedIndexChanged event of A, loop through the items in B and set some highlighting colors, ensuring visible etc. This works fine.
However... it would be nice to allow the user to MultiSelect. The problem here is the when selecting 10 items in A (holding the shift key down), the SelectedIndexChanged event fires 10 times, once for each item added into the selection. This is a real pain since my highlight sub then runs 10 times and it takes 10 times as long.
Now... I had a plan to deal with that, I detect the shift key being held down and inhibit the event until its raised. That works fine too.
But... if I have 10 items selected, and then I click one new one, so 10 are being deselected and one being selected, the SelectedIndexChanged event fires 11 times. So my situation has not improved. Any ideas how to wriggle out of this?, is there a better way?
-
Jan 29th, 2009, 08:36 PM
#2
Re: [2005] ListView SelectedIndexChanged
Would the ListView_ItemSelectionChanged event work better for you?
From that event, you get passed the item that as selected / unselected and the state of the item. From that could you just apply your conditional formatting for each individual item that was selected.
-
Jan 30th, 2009, 12:52 PM
#3
Re: [2005] ListView SelectedIndexChanged
But if the user does a multiselect, wont that event fire as many times as there are items in the selection?
So if 10 items are currently selected and the user then clicks a single new one, Im trying to avoid 11 events firing. I'll give it a try.
-
Jan 30th, 2009, 01:48 PM
#4
Re: [2005] ListView SelectedIndexChanged
Yeah the itemSelectionChanged event would still fire 11 times.
I really cant see how you could do this without just using a timer that gets started in the ItemSelectionChanged event and so then after about 200ms or whatever you process the SelectedItems collection.... but thats certainly not a great way of doing it.
-
Jan 30th, 2009, 02:04 PM
#5
Re: [2005] ListView SelectedIndexChanged
"then runs 10 times and it takes 10 times as long" unless you can actually tell a difference in the UI i wouldn't worry about it. otherwise you end up with code that is difficult to maintain for no real reason.
I wrote my very first programs in 1968 on a computer that didn't have words, know how to do math, didn't have a disk drive, didn't have a printer. i/o was an ibm "console" and punched cards.
-
Jan 30th, 2009, 06:07 PM
#6
Re: [2005] ListView SelectedIndexChanged
The issue is that it is obvious to the user, as the first listview clunks through each selected item, the other listview refreshes. Pick 1 item, with 20 deselecting and the user has to sit through that cycle 21 times.
I think I will just not allow multiselect as I cant see a way around it. Making a multiple selection is fine because I can detect the shift key down, but deselection is the problem. Not often I'll give up on a nifty feature but I think this one has defeated me.
-
Jan 30th, 2009, 06:54 PM
#7
Re: [2005] ListView SelectedIndexChanged
so there is a lot of code in the event? are you using
.BeginUpdate()
.EndUpdate()
it would help to actually see the code.
Last edited by dbasnett; Jan 30th, 2009 at 06:58 PM.
-
Jan 30th, 2009, 07:02 PM
#8
Re: [2005] ListView SelectedIndexChanged
Yes, I added that but I realised what was happening after a while. The code is fired on the SelectedIndexChanged event and loops through the other listview highlighting the relevant info.
I realised later that the changed event was triggering multiple times, so the code was running multiple times, not just once. So although I suspended the listview updating and various other tricks, the updating was visible.
There isnt that much code in the event, it loops through the selecteditems and for each item, loops through the other listview to highlight matching items.
I was just thinking about maintaining a variable which carries the selected items count value. If its large and the new selection is small, then looping just once (or something like that).
This is the current code that is called in the event. The Freeze and UnFreeze are SendMessage(CType(con.Handle.ToInt32, IntPtr), WM_SETREDRAW, False, 0) to stop any flicker.
Code:
Freeze(L)
L.BeginUpdate()
For Each cbi As ListViewItem In L.Items
If cbi.BackColor <> Color.Empty Then cbi.BackColor = Color.Empty
Next
L.EndUpdate()
UnFreeze(L)
Freeze(A)
If L.SelectedItems.Count > 0 Then
L.BeginUpdate()
A.BeginUpdate()
Dim first As Boolean = True
For Each lv As ListViewItem In A.Items
If lv.BackColor <> Color.Empty Then lv.BackColor = Color.Empty
Next
For Each cbi As ListViewItem In L.SelectedItems
For Each lv As ListViewItem In A.Items
If lv.SubItems(1).Text = cbi.Text Then
If lv.BackColor <> Color.Yellow Then lv.BackColor = Color.Yellow
If L.SelectedItems.Count = 1 Then
lv.EnsureVisible()
Else
If first Then lv.EnsureVisible()
End If
End If
Next lv
cbi.BackColor = Color.Yellow
first = False
Next
A.EndUpdate()
L.EndUpdate()
End If
UnFreeze(A)
Last edited by Bulldog; Jan 30th, 2009 at 07:07 PM.
-
Jan 30th, 2009, 08:13 PM
#9
Re: [2005] ListView SelectedIndexChanged
Well, what if you use the ListView_ItemSelectionChanged and only update the ones that match the item that was changed. That would take one of the loops out of your equation.
-
Jan 30th, 2009, 08:19 PM
#10
Re: [2005] ListView SelectedIndexChanged
But if I have 20 items selected and then I click one of the non-selected, does that event fire 21 times, or just once? (sorry I dont have the app in front of me to try it).
-
Jan 30th, 2009, 08:23 PM
#11
Re: [2005] ListView SelectedIndexChanged
Yes, but each run is only updating the the items of the other listview that apply to the item that was selected/unselected. So instead of having nested for loops, you have a single for loop that checks against the item passed in the eventarg.
-
Jan 30th, 2009, 08:30 PM
#12
Re: [2005] ListView SelectedIndexChanged
-
Jan 31st, 2009, 07:54 AM
#13
Re: [2005] ListView SelectedIndexChanged
it always helps to see the code. as negative said, just work on the item that changed.
Code:
Private Sub ListView1_ItemSelectionChanged(ByVal sender As Object, ByVal e As System.Windows.Forms.ListViewItemSelectionChangedEventArgs) Handles ListView1.ItemSelectionChanged
Dim i As Integer = e.ItemIndex
Debug.Write(i.ToString & " " & e.IsSelected.ToString & " ")
ListView2.BeginUpdate()
If e.IsSelected Then
'was not selected, now it is
Debug.WriteLine(DirectCast(e.Item, ListViewItem).Text)
Else
'was selected, now it is not
Debug.WriteLine(DirectCast(e.Item, ListViewItem).Text)
End If
ListView2.EndUpdate()
End Sub
-
Jan 31st, 2009, 08:40 AM
#14
Re: [2005] ListView SelectedIndexChanged
ok, I see what you mean (sorry I was being a bit dense). So the point is that it still fires multiple times, but the event code runs once per item, rather than looping all items, per item. I'll give that a go and see how it look.
-
Feb 15th, 2011, 10:31 AM
#15
New Member
Re: [2005] ListView SelectedIndexChanged
 Originally Posted by chris128
Yeah the itemSelectionChanged event would still fire 11 times.
I really cant see how you could do this without just using a timer that gets started in the ItemSelectionChanged event and so then after about 200ms or whatever you process the SelectedItems collection.... but thats certainly not a great way of doing it.
I stumbled onto this discussion thread by googling "ListView SelectedIndexChanged multiple times". Inside my SelectedIndexChanged event handler, I have a loop that iterates through all the selected items, so of course, the performance is order N^2, and gets progressively worse as the number of items in the ListView increases.
I fixed it as you describe--with the timer solution. I would dispute the comment, "thats certainly not a great way of doing it". I think it works like a charm, and is a very simple change from the way I was doing it before.
Before:
Code:
Sub _listView_SelectedIndexChanged(...)
' slow code
End Sub
After:
Code:
Sub _listView_SelectedIndexChanged(...)
_timer.Interval = 100
_timer.Enabled = True
End Sub
Sub _timer_Tick(...)
_timer.Enabled = False
' slow code here now
End Sub
-
Feb 17th, 2011, 03:43 AM
#16
Re: [2005] ListView SelectedIndexChanged
Yeah it might work better in this situation, its just that generally using a timer like that is not the best way of doing something - in some cases where you can't find any alternative then I guess it can be.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|