In another question I recently asked , I was told to use CompositeCollection to access various sources for a ListBox .
The example uses an XmlDataProvider to provide some dummy data. I, however, have a view model that contains data.
It took me a while to bind my ListBox to view model data. I finally figured it out, but now I would like to understand why my previous approaches did not work.
The key to success was CollectionViewSource. My initial attempts:
<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 a Window that has the appropriate DataContext and bind it to the data. You can do this through FindAncestor or through ElementName , so I tried both. It seemed to me very logical, but, apparently, I was mistaken. When I launched the application, I did not see anything.
I also tried to link to another control that has a data context; e.g. StackPanel .
So, why don't I get data with FindAncestor and ElementName 1 but do I need to explicitly specify CollectionViewSource ?
This is where the code works.
<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 did not forget to call this window and there was no typo.