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>