0

I have a hierarchy of observable collections, a bit like this:

interface IItem
{
    ObservableCollection<IItem> Children { get; }
}

Given an IItem (or an ObservableCollection<IItem>) I want to construct an other observable collection that recusively contains all child IItem items. This collection will then be used as the data source for a WPF list view (for example).

Modifying any of these items to have additional children should update the resulting observable collection. Note that there are no circular references.

I'm aware of the CompositeCollection Class and I'm sure that this should help me (I think that all I need is a composite collection recursively containining a composite collection for each child in Children), but I can't see a neat way to do this as this class doesn't have the ability to "template" children into the required composite collection.

SurvivalMachine
  • 7,946
  • 15
  • 57
  • 87
Justin
  • 84,773
  • 49
  • 224
  • 367
  • One way to do it would be to listen to the events on each child ObservableCollection and update the "flattened" list. – RQDQ Jul 24 '12 at 12:07
  • @RQDQ That was going to be my initial approach, however I realised that this could easily start to get very complex as I'd need to make sure that I recusively attach to and detach from the change events as children are added and removed in the heirachy. I saw the `CompositeCollection` class and hoped that there would be a simpler way. – Justin Jul 24 '12 at 12:10

1 Answers1

0

How are you using this flattened list? Do you need to enumerate it from time to time? Consider the following:

IEnumerable<Item> iterate(Item item)
{
     if (item == null)
          yield break;

     yield return item;

     foreach(Item i in item.Children)
     {
         foreach(Item ii in iterate(i){
            yield return ii;
         }
     }  
}

This essentially flattens the hierarchy and allows you to traverse all the items. Since it is lazy, it is always evaluated on the go. And is consistent with changes made to singular items in the hierarchy (as long as you don't enumerate and change at the same time).

EDIT:

The flattend collection is not a collection at all, it is a representation of a sequence of items that contains all the items in the hierarchy. Meaning that if you add (or remove) children from a certain item, you will get consistent results before and after the change.

Consider the following:

Item item = buildItemHierarchy(); var flat = iterate(item); item.Children.RemoveAt(2); // assume 2 exists

flat now 'contains' all the items from the original tree without the branch that sproted from the second child of the root (recursively!)

Vitaliy
  • 8,044
  • 7
  • 38
  • 66
  • It needs to be observable, so that if items are added to / removed from any of the children collections the flattened collection updates too. – Justin Jul 24 '12 at 12:58
  • Its still not observable - if the heirachy is modified then I won't be notified about that change and I'd only see that change the next time I enumerate through the collection. Imagine that the collection is going to be used as the data source for a WPF list view. – Justin Jul 24 '12 at 14:27
  • I see. That is why I asked how are you using the flattened list... :-) – Vitaliy Jul 24 '12 at 15:49