TLDR version...
We're trying to create as basic Panel subclass with an observable Items property. The control then uses those data items to create one or more related child UI objects per data item.
Our first thought naturally was to simply subclass ItemsControl, but that doesn't seem to fit because it uses an ItemContainerGenerator which only generates one 'container' per item whereas again, we need to potentially create several (which aren't containers anyway.) Plus, all the created items have to be direct children on the panel, not held in a container which is why we can't go the route of data templates.
As such, I'm just using a standard Control and I'm trying to find the proper place/event where I should be instantiating/destroying the resulting child UI elements in response to changes in the Items collection.
Now the details...
First things first. If there was something like a ItemMultiContainerGenerator, that would be perfect, but I know of no such thing.
Ok, so simply monitor the collection for changes and put the UI generation in the CollectionChanged event! Right? That was our first guess too. The problem there is for every new 'Add' or 'Remove', we have to spin through all existing controls to 'defrag' certain indexing properties on them (think along the lines of a Grid.Row or ZIndex property) meaning if you add ten items, you run the defrag ten times, not once at the end.
Plus, that change event may come in on a different thread. If you attempted to dispatch to the main thread, your performance takes a nose-dive.
Our other attempt was to use MeasureOverride, since that was called only once in response to an InvalidateMeasure call, regardless of how many children we added or removed. The issues (there are many) with this approach is we lose context of whether something was added or removed, meaning we had to throw away all children and re-add back all new ones making this extremely inefficient. Plus, mucking around with the visual tree or setting bindings could cause the layout pass to execute multiple times since we were changing something that affects the layout, namingly the panels children.
What I'm trying to find is something that happens as part of the overall rendering process (i.e. from the time the control is told its invalid until it renders), but before the Measure/Layout passes are called. That way I can cache the adds/removes in the CollectionChanged event and simply mark the control as invalid, wait for this mystery event, then process the changes en mass, then send off the results to the layout engine and be done with it.
Using Reflector, I've tried to find out where the ItemsControl adds its children to the panel, but I didn't get too far considering the complexity of the control/ItemContainerGenerator pairing.
So where is the best place to create/add UI elements to a control based on data item changes?