Using ObservableCollection with Linq

It’s not easy. Let’s say you’ve got a composite object which contains an observable collection (because you want to bind it to a list box for example). Then let’s say you want to populate this from a Linq query (Linq to XML for example). You soon run into the rather large gap becaue, unlike List<T>, ObservableCollection doesn’t have a suitable way to initialise it with a collection (not one that’s suitable for use in a Linq query.

Here’s how I fixed it in my project first. Rather than simply using ObservableCollection<PictureData> directly, create a new class that overrides it and adds an additional constructor:


    public class PictureDataList : ObservableCollection<PictureData>
    {
        public PictureDataList()
        {
        }

        public PictureDataList(IEnumerable<PictureData> items)
        {
            foreach (var item in items)
            {
                Add(item);
            }
        }
    }

This method can be safely used in any Linq query.

But there’s a slightly better way – one which avoids having to code up a specific class for each type of object we want. We can add an extension method to ObservableCollection to populate the list from an IEnumerable, like this:


public static class LinqHelper
{
    public static ObservableCollection<T> PopulateFrom<T>(this ObservableCollection<T> collection, IEnumerable<T> range)
    {
        foreach (var x in range)
        {
            collection.Add(x);
        }
        return collection;
    }
}

You can use this in any linq select queryby doing:


var query = from regel in document.Element("Regions").Elements("Region")
                             select new MapRegion(this)
                             {
                                 Category = regel.Element("Category").Value,
                                 Description = regel.Element("Description").Value,
                                 Title = regel.Element("Title").Value,
                                 Route = new Route(regel.Element("Route")) { map = mapControl },
                                 Pictures = new ObservableCollection<PictureData>().PopulateFrom( 

                                     from pixel in regel.Element("Pictures").Elements("Picture")
                                     select new PictureData()
                                     {
                                         Picture = pixel.Element("Url").Value,
                                         Audio = pixel.Element("Audio").Value
                                     })
                             }

About these ads

3 thoughts on “Using ObservableCollection with Linq

  1. Thanks good idea. Helped me out. I tweaked this approach to target the extension method on IEnumerable so it can be used just like .ToList() after an LINQ Query and called it ToObservableCollection:

    public static ObservableCollection ToObservableCollection(this IEnumerable source)
    {
    ObservableCollection collection = new ObservableCollection();

    foreach (var item in source)
    {
    collection.Add(item);
    }

    return collection;
    }

    • Thanks, Litle Modification though

      public static ObservableCollection ToObservableCollection(this IEnumerable source)
      {
      ObservableCollection collection = new ObservableCollection();

      foreach (var item in source)
      {
      collection.Add((T)item);
      }

      return collection;
      }

  2. This looks pretty cool.
    I’m trying to figure out an easy way to fill a treeview from Linq to SQL, and also have it reflect changes.
    Implementing INotifyPropertyChanged doesn’t seem to work all by itself.
    Now I just have to figure out how to convert this solution over to VB.Net…

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s