20

I do not get the correct Binding syntax to access the Cats and Dogs properties of MyViewModel within a DateTemplate that defines a CompositeCollection within its resources.

public class MyViewModel
{
    public ObservableCollection<Cat> Cats { get; private set; }
    public ObservableCollection<Dog> Dogs { get; private set; }
}
<DataTemplate DataType={x:Type local:MyViewModel}">
  <DataTemplate.Resources>
    <CompositeCollection x:Key="MyColl">
      <!-- How can I reference the Cats and Dogs properties of MyViewModel? -->
      <CollectionContainer Collection="{Binding Dogs, ????}">
      <CollectionContainer Collection="{Binding Cats, ????}">
    </CompositeCollection>
  </DataTemplate.Resources>
  <ListBox ItemsSource="{StaticResource MyColl}">
    <!-- ... -->
  </ListBox>
</DataTemplate>

What do I have to insert for ???? to bind the Dogs and Cats collections to the CollectionContainers?

H.B.
  • 166,899
  • 29
  • 327
  • 400
Oliver
  • 1,507
  • 1
  • 12
  • 23

2 Answers2

57

Due to the issue with data binding on CollectionContainer as described http://social.msdn.microsoft.com/Forums/vstudio/en-US/b15cbd9d-95aa-47c6-8068-7ae9f7dca88a/collectioncontainer-does-not-support-relativesource?forum=wpf I now use the following approach:

<ListBox>
  <ListBox.Resources>
    <CollectionViewSource x:Key="DogCollection" Source="{Binding Dogs}"/>
    <CollectionViewSource x:Key="CatCollection" Source="{Binding Cats}"/>
  </ListBox.Resources>
  <ListBox.ItemsSource>
    <CompositeCollection>
      <CollectionContainer Collection="{Binding Source={StaticResource DogCollection}}"/>
      <CollectionContainer Collection="{Binding Source={StaticResource CatCollection}}"/>
    </CompositeCollection>
  </ListBox.ItemsSource>
  <!-- ... -->
</ListBox>

Edit: The CompositeCollection class does not derive from FrameworkElement and thus does not have a DataContext property to support data binding. It will only work if you use Binding providing a Source. Have a look here https://stackoverflow.com/a/6446923/1254795 for more information.

Community
  • 1
  • 1
Oliver
  • 1,507
  • 1
  • 12
  • 23
  • This works great for me. But it would be more helpful if you could explain _why_ this is required. I don't understand: **1)** why can't I declare a `CollectionContainer` resource the same way and use it directly, instead of indirecting through the `CollectionViewSource`? and **2)** why can't I declare a `CompositeCollection` as a resource and just bind to `CollectionContainer` objects within directly? What is so special about `CollectionViewSource` that it works here even when other types won't? – Peter Duniho Feb 23 '16 at 00:45
4

Try giving your ListBox a name and refer to its DataContext in the bindings:

<ListBox x:Name="myList" ItemsSource="{DynamicResource MyColl}">
   <ListBox.Resources>
      <CompositeCollection x:Key="MyColl">
         <CollectionContainer Collection="{Binding DataContext.Dogs, Source={x:Reference myList}}"/>
         <CollectionContainer Collection="{Binding DataContext.Cats, Source={x:Reference myList}}"/>
      </CompositeCollection>
   </ListBox.Resources>
</ListBox>
thatguy
  • 21,059
  • 6
  • 30
  • 40
Nitin
  • 18,344
  • 2
  • 36
  • 53
  • This does not work. I get an exception that the name of the `ListBox` can not be resolved. I think this is due to the fact that the `CompositeCollection` is declared within `DataTemplate.Resources` and the `ListBox` is declared after. – Oliver Oct 08 '13 at 09:07
  • just a suggestion.. why do you want collection in template resources.. can you move this in ListBox resources? – Nitin Oct 08 '13 at 09:08
  • If I move the `CompositeCollection` to `ListBox.Resources` then how I can reference it as `ListBox.ItemsSource`? – Oliver Oct 08 '13 at 09:12
  • instead of StaticResource use `{DynamicResource MyColl}` – Nitin Oct 08 '13 at 09:22
  • Circular reference: This problem occurs if you use `x:Reference` within the element you want to reference. This post [http://stackoverflow.com/questions/6446699/how-do-you-bind-a-collectioncontainer-to-a-collection-in-a-view-model](http://stackoverflow.com/questions/6446699/how-do-you-bind-a-collectioncontainer-to-a-collection-in-a-view-model) describes this problem too. It says that you have to move the `CompositeCollection` to the resources and use `StaticResource` - what I tried. But then I don't know how to bind the `CollectionContainer` to the ViewModel properties. Circular problem ;-) – Oliver Oct 08 '13 at 09:25
  • 1
    it wont give the cyclical error in case you put collectin in your listbox resources and use dynamicresource to refer it... just tested this... working fine.. updated the answer with the tested code – Nitin Oct 08 '13 at 09:31
  • Can you give me a code sample for this? I tried it and it did not work. – Oliver Oct 08 '13 at 09:33
  • This does not work, brings me an XamlParseException: Cannot call MarkupExtension.ProvideValue because of a cyclical dependency. Properties inside a MarkupExtension cannot reference objects that reference the result of the MarkupExtension. The affected MarkupExtensions are: System.Windows.Data.Binding – Oliver Oct 08 '13 at 09:45
  • This works fine for me. However, the XAML editor complains with a `NullReferenceException` (i.e. "Object reference not set to an instance of an object"). It works fine at runtime, but the editor error is annoying; any way to declare this in a way that won't result in the editor error? – Peter Duniho Feb 23 '16 at 00:18
  • @Oliver You can in fact also reference the collection using `StaticResource`, but because of the sequential processing of XAML, you have to specify the `ItemsSource` after the `` section for it to work. e.g.: ``. – thatguy Oct 28 '20 at 11:21