14

I'm binding ItemsControl to CollectionViewSource. Here is code:

this.Trucks = new ObservableCollection<Truck>();
            foreach (var truck in DataRepository.Trucks.Where(t => t.ReadyDate.Date.Equals(this.Date)))
            {
                this.Trucks.Add(truck);
            }

            this.TrucksSource = new CollectionViewSource { Source = this.Trucks };
            this.TrucksSource.SortDescriptions.Add(new SortDescription("ReadyAddress.Region.RegionNumber", ListSortDirection.Ascending));
            this.TrucksSource.SortDescriptions.Add(new SortDescription("TruckId", ListSortDirection.Ascending));

When I initially bind - sorting works. When I add item to ObservableCollection - it is inserted in proper spot, thats good. But when I change property which I sort by - this item is not being "shifted" in a list.

ReadyAddress.Region.RegionNumber properly raises INotifyPropertyChanged and I see it in bound fields, but order does not change. Do I expect something that shouldn't happen or there is better way to handle this?

katit
  • 17,375
  • 35
  • 128
  • 256
  • 1
    Please see my answer for [SortDescription and automatic sorted order refresh](http://stackoverflow.com/a/7372522/620360). – LPL Jun 30 '12 at 17:15
  • 1
    There is new feature in WPF 4.5 called live shaping that solves this problem but you may have to use the method linked to by LPL for the time being if you don't want to call Refresh. – Kris Jul 01 '12 at 01:22
  • I was able to fix this by simply calling PropertyChanged on the property that exposes the view, letting the view refresh (and clear out the sort) and then adding the sort descriptions. – PatFromCanada Jun 12 '13 at 15:30

3 Answers3

13

Late answer, but with 4.5 the ListCollectionView (the default implementation for a ListBox and CollectionViewSource.View) new properties were added to make this possible.

You can use the IsListSorting and ListSortingProperties to enable automatic resorting. And no, it does not rebuild the view

list.SortDescriptions.Add(new SortDescription("MyProperty", ListSortDirection.Ascending));
list.IsLiveSorting = true;
list.LiveSortingProperties.Add("MyProperty");

This should resort when the property MyProperty changes.

Shawn Kendrot
  • 12,425
  • 1
  • 25
  • 41
  • In XAML you can use IsLiveSortingRequested="True" property of CollectionViewSource: where xmlns:cm="clr-namespace:System.ComponentModel;assembly=WindowsBase" – Ivanhoe Jul 06 '23 at 13:27
5

Have you tried refreshing your collectionviewsource?

    this.TruckSource.View.Refresh();
Bambu
  • 548
  • 6
  • 16
5

All answers I found mentioned View.Refresh() but that's not very good solution for big lists. What I ended up doing was to Remove() and Add() this item. Then it was properly repositioned without reloading whole list.

Word of caution! It works for what I do, but in your case removing object and re-adding may cause side effect depending how your code written. In my case it's a list with UI effect where new items show up with transition so refreshing will show transition on whole list where remove/add nicely shows how item get's repositioned.

katit
  • 17,375
  • 35
  • 128
  • 256