In another question I recently asked, I was told to use a CompositeCollection
in order to access various sources for a ListBox
.
The example used a XmlDataProvider
to provide some dummy data. I, however, have a view model, which contains the data.
It took me some time to bind my ListBox
against the view model's data. Eventually I figured it out, but now I'd like to understand why my previous approaches didn't work.
The key to success was a CollectionViewSource. My initial attempts were:
<CollectionContainer Collection="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.Movies}"/>
<CollectionContainer Collection="{Binding ElementName=Window, Path=DataContext.Movies}"/>
My idea was to find the Window, which has the appropriate DataContext, and bind against the data. You can do that via FindAncestor
or via ElementName
, so I tried both. That seemed very logically to me, but apparently I was wrong. I didn't see nothing when I ran the application.
I also tried binding against another control which has the data context; e.g. the StackPanel
.
So, why don't I get the data with FindAncestor
and ElementName
1, but have to provide a CollectionViewSource
explicitly?
Here's the code that is working.
<StackPanel DockPanel.Dock="Top">
<ListBox ItemTemplateSelector="{StaticResource CustomDataTemplateSelector}">
<ListBox.Resources>
<CollectionViewSource x:Key="ViewSource" Source="{Binding Movies}"/>
</ListBox.Resources>
<ListBox.ItemsSource>
<CompositeCollection>
<CollectionContainer Collection="{Binding Source={StaticResource ViewSource}}"/>
<CollectionContainer Collection="{Binding Source={StaticResource MyButtonsData}}"/>
</CompositeCollection>
</ListBox.ItemsSource>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True"
Width="{Binding (FrameworkElement.ActualWidth),
RelativeSource={RelativeSource AncestorType=ScrollContentPresenter}}"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</StackPanel>
1 No, I didn't forget to name the window and there wasn't a typo either.