Sebastian
Sebastian

Reputation: 4811

Sorting ItemsControl in WPF fastest way

Sorting takes a lot of time to finish . I am using an ItemsControl WPF element to show a list of items ( An observable Collection) and i want to sort this Observable Collection based on a property I used this code for doing the sort operation

        ICollectionView dataView = CollectionViewSource.GetDefaultView(mycontrolName.ItemsSource);
        dataView.SortDescriptions.Clear();
        SortDescription sd = new SortDescription("Property", ListSortDirection.Ascending);
        dataView.SortDescriptions.Add(sd);
        dataView.Refresh();

But its taking a lot of time to reflect the changes on UI. Once i click the sort button it took almost 8-10 seconds to render the sorted view . Any idea to improve this perfomance ( My list contains more than 100 items and every list item consists of some images and few text properties ).

The xaml i used is

<ItemsControl  ItemsSource="{Binding ShelfItemsCollection}" Name="shelfGridView" Margin="5" Visibility="Collapsed"VirtualizingStackPanel.IsVirtualizing="True"
ScrollViewer.CanContentScroll="False"   VirtualizingStackPanel.VirtualizationMode="Recycling"  >
            <ItemsControl.ItemTemplate>
                    <DataTemplate> 
        <Border Style="{StaticResource ResourceKey=shelfBorderStyle}" MinWidth="200">
  <Stackpanel>
 <Image Width="150" Height="200" Stretch="Fill" Source="{Binding CoverImage}" ></Image> 
    <TextBlock Text="{Binding Title}"  TextTrimming="CharacterEllipsis"  MaxWidth="150"></TextBlock>
   <TextBlock Text="{Binding Info}"  TextTrimming="CharacterEllipsis"  MaxWidth="150"  ></TextBlock>
 </StackPanel>
</Border> 

Upvotes: 1

Views: 2695

Answers (2)

pushpraj
pushpraj

Reputation: 13669

sorting 100 item based on a single property could probably never take 8-10 seconds on today's processors, there is something seriously wrong with the view.

if I am not wrong and it is related to your previous question. follow the steps below

  • remove ScrollViewer.CanContentScroll="False" from the main listbox if it is there.
  • add VirtualizingStackPanel.IsVirtualizing="True" to the listbox
  • also add VirtualizingStackPanel.VirtualizationMode="Recycling" to the same listbox

this will definitely solve the rendering issue

image loading issue

  • you need to defer the loading of external images or load them asynchronously
  • you may show a placeholder while image is loading
  • also suggested do not load all the images while populating the collection, only load when it is required to be on the view.

Update

I found an issue in your code, it is due to incompatible type of a property Progress in LocalLibrary.

this property is bound to progress-bar's value property which is of type double and in model this property as defined as string.

this cause an exception while data conversion, also slows down adding, sorting, removal etc. more the items more are exceptions, and while debugging such exceptions are logged in output window so delay is even more.

original error from output window, this is a good source of debugging wpf issues.

'SystemConvertConverter' converter failed to convert value '<null>' (type '<null>'); fallback value will be used, if available. BindingExpression:Path=Progress; DataItem='LocalLibrary' (HashCode=46519225); target element is 'ProgressBar' (Name=''); target property is 'Value' (type 'Double') InvalidCastException:'System.InvalidCastException: Null object cannot be converted to a value type.

so by changing this property alone to a compatible type ie. double will improve performance significantly

    private double progress { get; set; }

    public double Progress
    {
        get { return progress; }
        set
        {
            progress = value;
            NotifyChange(new PropertyChangedEventArgs("Progress"));
        }
    }

Upvotes: 2

Aron
Aron

Reputation: 15772

Try this

    ICollectionView dataView = CollectionViewSource.GetDefaultView(mycontrolName.ItemsSource);
    using(dataView.DeferRefresh())
    {
       dataView.SortDescriptions.Clear();
       SortDescription sd = new SortDescription("Property", ListSortDirection.Ascending);
       dataView.SortDescriptions.Add(sd);
    }

I suspect some of the slow down is because you are in effect refreshing the view 3 times.

  1. dataView.SortDescriptions.Clear();
  2. dataView.SortDescriptions.Add(sd);
  3. dataView.Refresh();

DeferRefresh will reduce that to a single refresh. Still that should only reduce it down to about 2second...which is still pretty damned slow.

http://msdn.microsoft.com/en-us/library/system.windows.data.collectionview.refresh(v=vs.110).aspx#remarksToggle

Upvotes: 1

Related Questions