How do you bind a CollectionContainer to a collection in a view model?

Solution 1:

The CompositeCollection has no DataContext, the bindings in the CollectionContainers will not work if they bind directly to a property (which implicitly uses the DataContext as source).

You need to explicitly specify a source, i would suggest you name the control with your DataContext and use x:Reference to get it (ElementName will not work) or you use a StaticResource, e.g.

<CollectionContainer Collection="{Binding DataContext.GreekGods, Source={x:Reference myStackPanel}}"/>
<CollectionContainer Collection="{Binding GreekGods, Source={StaticResource CompositeCollectionVM}}"/>

Note that when using x:Reference the compiler easily trips you up with cyclical dependency errors, to avoid those place your CompositeCollection in the resources of the control you reference, then insert it wherever it belongs using the StaticResource markup extension.

Solution 2:

An IMultiValueConverter is a nice fit for CompositeCollection but not for your specific case where you add stuff in xaml.

Converter:

using System;
using System.Collections;
using System.Globalization;
using System.Windows.Data;

public class CompositeCollectionConverter : IMultiValueConverter
{
    public static readonly CompositeCollectionConverter Default = new CompositeCollectionConverter();

    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        var compositeCollection = new CompositeCollection();
        foreach (var value in values)
        {
            var enumerable = value as IEnumerable;
            if (enumerable != null)
            {
                compositeCollection.Add(new CollectionContainer { Collection = enumerable });
            }
            else
            {
                compositeCollection.Add(value);
            }
        }

        return compositeCollection;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException("CompositeCollectionConverter ony supports oneway bindings");
    }
}

Usage:

<ListBox>
    <ListBox.ItemsSource>
        <MultiBinding Converter="{x:Static local:CompositeCollectionConverter.Default}">
            <Binding Path="Col1" />
            <Binding Path="Col2" />
            ...
        </MultiBinding>
    </ListBox.ItemsSource>
    ...
</ListBox>