Jakub Wisniewski
Jakub Wisniewski

Reputation: 2249

Order ObservableCollection for ListView

I have problem with ordering data for ListView. I have EventDisplay class which is an ObservableCollection for ListView(called Events)

private ObservableCollection<EventDisplay> currentEvents = new ObservableCollection<EventDisplay>();

private void Events_Loaded(object sender, RoutedEventArgs e)
{
    sv = (ScrollViewer)VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(this.Events, 0), 0);

    Events.ItemsSource = currentEvents;            
}

I then add new data by function :

private void LoadDataToList(List<EventDisplay> newItems)
{
        foreach (EventDisplay ed in newItems)
        { 
            //Set some additional data
            currentEvents.Add(ed);
        }   
        //When this line below is commented ListView data is updated
        //but is not sorted, when i uncomment the listview data is not being updated

        //currentEvents = new ObservableCollection<EventDisplay>(currentEvents.OrderByDescending(x => x.ed.date).ToList());                   
    }

So what is the proper way of ordering data for ListView in Windows 8.1 apps ?

Upvotes: 0

Views: 1200

Answers (3)

Arie
Arie

Reputation: 5373

You can sort & filter the view of your ObservableCollection (explanation here)

public class ViewableCollection<T> : ObservableCollection<T>
    {
        private ListCollectionView _View;
        public ListCollectionView View
        {
            get
            {
                if (_View == null)
                {
                    _View = new ListCollectionView(this);
                }
                return _View;
            }
        }
    }

Data structure for the example:

interface ICustomer
{
   string CuctomerName{get;set;}
   int Age{get;set;}
}

Example use of the code:

ViewableCollection<ICustomer> vCustomers = new ViewableCollection<ICustomer>();
// Sorting settings:
ViewableCollection<ICustomer> vCustomers.View.SortDescriptions.Add(new SortDescription("CustomerName", ListSortDirection.Ascending));
vCustomers.View.Filter = MyCustomFilterMethod;
// add data to collection
MyCustomers.ToList().ForEach(customer => vCustomers.Add(customer));

Examlpe filter method:

private bool MyCustomFilterMethod(object item)
{
    ICustomer customer = item as ICustomer;
    return customer.Age > 25;
}

when you need to refresh the filter, the only thing you need to do is call:

this.vCustomers.View.Refresh();

Then you bind your GUI to vCustomers.View You don't need to reset binding sources etc.

Upvotes: 1

TiMoch
TiMoch

Reputation: 1048

You should do the following :

currentEvents = new ObservableCollection<EventDisplay>(currentEvents.OrderByDescending(x => x.ed.date).ToList()); 
Events.ItemsSource = currentEvents;

This forces the ListView to rebind to your new sorted observable collection.

Another option is to sort the Observable collection in place. However, it may introduce flickering as the ListView will constantly update as the sort progresses.

If you don't want the ScrollView to reset its position, you can save the scrollview position and then restore it after sorting the list. I've had success with Implementing a custom ObservableCollection that supports sorting but prevents UI flickering by suspending change notification during sort and then issuing a reset notification. The ScrollView should stay at its current position even when confronted with the reset event.

Upvotes: 1

toadflakz
toadflakz

Reputation: 7944

Use this for your add items code:

    foreach (EventDisplay ed in newItems.OrderByDescending(x => x.ed.date).ToList()
    { 
        //Set some additional data
        currentEvents.Add(ed);
    }  

The reason your doesn't work is that you are reassigned the currentEvents reference rather than updating the ObservableCollection.

Upvotes: 1

Related Questions