May 14, 2007
06:10 PM

Here's a simple LINQ query in C# 3.0:

var people = new ObservableCollection<Person>();
var friends = new ObservableCollection<string>();

var myFriendsAges = 
    from p in people
    join f in friends on p.Name equals f
    select p.Age;

Using ObservableCollection<T> from .NET 3.0 doesn't buy us anything that List<T> wouldn't. We end up creating an ordinary sequence, IEnumerable<int>. But, it doesn't have to be this way, LINQ is easily extended. Read on.

For use in RikReader's hierarchical view I implemented a new collection class, StackedList<T>. This is similar to System.Windows.Data.CompositeCollection in that I can flatten multiple collections into a single list. But StackedList is far more generic, it will directly flatten any IList<T>, and should the child list implement INotifyCollectionChanged, the collection change events are remapped such that StackedList is able to provide a complete read-only illusion of a virtual collection.

StackedList<int> list = new StackedList<int>();
Console.WriteLine(list.Count); // -> "0"

ObservableCollection<int> childList = new ObservableCollection<int>();
childList.Add(1);
list.AddCollection(childList);
Console.WriteLine(list.Count); // -> "1"

childList.Add(2);
Console.WriteLine(list.Count); // -> "2"
Console.WriteLine("{0}, {1}", list[0], list[1]); // -> "1, 2"

If we tried to write the same program using CompositeCollection we'd probably end up with something like this:

CompositeCollection composite = new CompositeCollection();
CollectionView view = CollectionViewSource.GetDefaultView(composite) as CollectionView;
Console.WriteLine(view.Count); // -> "0"

ObservableCollection<int> childList = new ObservableCollection<int>();
childList.Add(1);
CollectionContainer container = new CollectionContainer();
container.Collection = childList;
composite.Add(container);
Console.WriteLine(view.Count); // -> "1"

Even though CollectionView has a Count property, it doesn't implement IList, it actually exposes a new list like interface ICollectionView which is IEnumerable. CollectionView is also non-generic, but notwithstanding, it is a similar approach.

With StackedList I was easily able to flatten a hierarchy of Feeds and Folders into a single, observable list of Items - which was then directly bindable for visualisation.

Stay tuned for Part 2, where we will explore the application of some other virtual lists.

© Douglas Stockwell 2007
Creative Commons License Unless otherwise specified all "source code" examples are available for use under the Creative Commons Attribution-Noncommercial 3.0 License. Please contact me if you would like more flexible licensing terms.
Messenger Presence