views:

130

answers:

3

I try to programmatically update the selected items in a listbox, with extended selection mode.
Here is how I do it:

foreach (var selectedItem in ItemsForSelection)
{
  _myList.SelectedItems.Add(selectedItem);
}

My problem is, that when the number of the selected items is big, the update is very slow.
The root of the problem is that listbox doesn't derrive from MultiSelector, which can be tweaked to perform a fast bulk update, by using the methods BeginUpdateSelectedItems and EndUpdateSelectedItems.
Is there a way to get a similar result in a listbox?

A: 

Is there a BeginUpdate and EndUpdate method available in the ListBox...

_myList.BeginUpdate();
foreach (var selectedItem in ItemsForSelection)
{
  _myList.SelectedItems.Add(selectedItem);
}
_myList.EndUpdate();

That is assuming that _myList is a ListBox...The pair for Begin/End Update methods freezes the WM_PAINT message and unfreezes respectively thereby making it flicker free and fast.

Hope this helps, Best regards, Tom.

tommieb75
If I had those methods, I wouldn't ask the question.I also don't think that it has something to do with WM_PAINT - the slowness is a result of many raised ListChanged events, and slow listbox internal logic.
Andy
@Andy: Fair enough, it exists under the WinForms, and it does the job, if you were adding loads of items to the listbox, that's what makes it appear snappy and quick. Am not sure about WPF unless the component is different. WinForms ListView has that, that's for sure, again, not 100% confident if that's in WPF...Why don't you temporarily remove the event handlers first prior to adding to the list and re-add them again after it's done?
tommieb75
A: 

After adding a chunk of items, try pumping the dispatcher by pushing a dispatcher frame into the dispatcher.

http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcherframe.aspx

dhopton
How's that gonna help? I assume that I need to prevent from internal list box logic to be performed whenever each one of the items is selected, i.e. I need to prevent ListChanged event handling, on each one of the changes in the SelectedItems list.
Andy
It's likely to actually speed it up since each operation will be handled incrementally, rather than the UI hanging or appearing so while your adding items to the selection. it's quite possible the end to end time for complete reselection will be higher, but the user won't think like that -- they'll see the app working.
dhopton
A: 

There is a SetSelectedItems(IEnumerable) available on ListBox you could use. This function wraps selection changes in a SelectionChange.Begin/End (unfortunately only available internally of course) which ought to result in only a single selection change event going out.

Note that SetSelectedItems is protected, so you'll have to use your own ListBox derivative to call it. Odd choice, that.

Scott Bilas
Bah..I just tested and while it does wrap the selection changes, it still ends up firing one Add event per item in the new selection set. Even though the event supports ranges, they do it one at a time. Really lame. My workaround is to wrap the call in base.SetSelectedItems in a begin/end of my own that temporarily suspends my handler for change notifications, and restores it after the new set is in place, doing a reset of my local observable collection.
Scott Bilas