In my latest WPF version of Comicster, I've been having some performance problems when trying to sort large numbers of issues.

My collection of about 1,100 comics is pretty measly when compared to those of serious collectors', and one file I have from a user has about 10,000 issues in it. When I first open the collection, the root "Owned" folder has focus, so the issue list is populated with every issue in the collection.

Now, populating a ListBox with 10,000 items in WPF is not really a problem, because the ListBox control uses a VirtualizingStackPanel as its default panel. That means that it only needs to worry about the items that are currently displayed, so it should be lightning fast.

The problem is that I'm trying to sort the issues before they're displayed (using CollectionView.SortDescriptions). Sorting 10,000 items by four different properties is slow - there's just no getting around that.

What to do? The issues ListBox is agnostic when it comes to its data source - I couldn't sort it sometimes and not others.

In the end I came up with this idea: An IValueConverter which, given a CollectionView, sorts it if it has fewer than 1000 items. This seems reasonable, because really you only care about sorting if you're viewing a folder, trade or title with a reasonable number of issues. My XAML to use it looks like this:

<Setter Property="ItemsSource">
<
Setter.Value>
<
Binding
Source="{StaticResource CollectionIssuesView}"
Converter="{StaticResource IssueViewConverter}"
ConverterParameter="1000"
</
Setter.Value>
</
Setter>

As you can see, I've set it up in such a way that you can override the sorting threshold using the ConverterParameter property.

Here's the IssueViewConverter's Convert method for your reference (reformatted slightly so it doesn't take up too much horizontal space):

public object Convert(object value, Type targetType, 

object parameter, CultureInfo culture)
{
var view = value as CollectionView;
if (view == null) return value;
var threshold = parameter == null ? 1000
: System.Convert.ToInt32(parameter);
if (view.Count < threshold)
{
view.SortDescriptions.Clear();
view.SortDescriptions.Add(
new SortDescription("Title.Name",
ListSortDirection.Ascending));




view.SortDescriptions.Add(
new SortDescription("Title.Volume",
ListSortDirection.Ascending));
view.SortDescriptions.Add(
new SortDescription("Title.Year",
ListSortDirection.Ascending));
view.SortDescriptions.Add(
new SortDescription("SortOrder",
ListSortDirection.Ascending));
}
return view;
}