Skip to content

ObservableCollectionView

Rico Suter edited this page Jun 3, 2015 · 7 revisions
  • Package: MyToolkit
  • Platforms: All (PCL)

Collection which can be used to sort and filter an existing collection. The view itself is an observable collection and is therefore meant to be used in XAML bindings.

var source = new ObservableCollection<Person>();
var view = new ObservableCollectionView<Person>(source);

// Set ordering and filter
view.Order = p => p.Age;
view.Filter = p => p.Age > 20;

// Add a new person to the original source
source.Add(new Person { Age = 10 });
<ListBox ItemsSource="{Binding view}" />

If the constructor is not called with a list, a new ObservableCollection<TItem> will be created which can be accessed using the Items property.

// using the observable view without source list
var view = new ObservableCollectionView<Person>();
// access the source list by using the Items property
view.Items.Add(new Person { Age = 20 });

If the source collection is an observable collection all changes are propagated to the ObservableCollectionView and all items are always sorted and filtered correctly. If you set TrackItemChanges flag to true, the view also listens to property changes of all items and resorts and filters the list if a property of an item has been changed.

Every change in the original source forces the view to refilter and resort the collection. If you have to add a lot of items, you should disable item tracking until all items have been added:

view.TrackCollectionChanges = false;
foreach (var item in collection)
    source.Add(item);
view.TrackCollectionChanges = true; // this will force a refiltering and resorting

// or use
view.AddRange(collection);

The ObservableCollectionView uses weak events to register on the original source list to avoid memory leaks, but you should always call Dispose to correctly delete the view.

Usage in a view model

The following code shows how to use the ObservableCollectionView in a view model:

public class MySampleViewModel : ViewModelBase
{   
    private string _categoryFilter = string.Empty;

    public MySampleViewModel()
    {
        AllEntries = new ExtendedObservableCollection<MyEntry>(); 
        FilteredEntries = new ObservableCollectionView<MyEntry>(AllEntries);
    }
    
    public ExtendedObservableCollection<MyEntry> AllEntries { get; private set; } 
    
    public ObservableCollectionView<MyEntry> FilteredEntries { get; private set; }

    public string CategoryFilter
    {
        get { return _categoryFilter; }
        set 
        {
            if (Set(ref _categoryFilter, value))
            {
                FilteredEntries.Filter = entry => 
                    string.IsNullOrEmpty(_categoryFilter) || 
                    entry.Category == _categoryFilter;
            }
        }
    }
    
    public async Task LoadEntries()
    {
        var entries = await MyLoader.LoadEntriesAsync(); // TODO: Implement this
        AllEntries.Initialize(entries);
    }   
}

public class MyEntry
{
    public string Title { get; set; }
    public string Category { get; set; }
} 

Now you can bind to the FilteredEntries property in your XAML view.

Clone this wiki locally