2

I have a ComboBox that has a bound items source... I've stripped my example down to the key pieces:

<UserControl x.Class="My.Application.ClientControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"                         
             xmlns:conv="clr-namespace:My.Utilities.Converters"
             Name="ClientControl">

    <UserControl.Resources>
        <ResourceDictionary>
            <CollectionViewSource Key="x:ClientsCollection" />
        </ResourceDictionary>

        <conv:ClientOptions x:Key="ClientOptions" />

    </UserControl.Resources>

    ...

    <ComboBox Name="Options" 
              DataContext="ClientsCollection" 
              ItemsSource="{Binding [ClientNumber], Converter={StaticResource ClientOptions}" />

</UserControl>

This works, but I now want to add a single manual item to my combobox that will trigger alternate functionality called "Other..." so I'm having to move to using the CompositeCollection... like so:

<ComboBox Name="Options"
          DataContext="ClientsCollection">
    <ComboBox.ItemsSource>
        <CompositeCollection>

            <CollectionContainer Collection="{Binding [ClientNumber], Converter={StaticResource ClientOptions} />
            <ComboBoxItem>Other...</ComboBoxItem>
        </CompositeCollection>
</ComboBox>

Try as I might, the bound items just won't populate when using the CompositeCollection. It only shows the manual ComboBoxItem "Other...". If I remove that item, the list is empty. If I attach a breakpoint to the converter it doesn't catch anything, which seems to indicate that the binding isn't even attempted.

I am obviously not understanding something about how the binding function in the CompositeCollection is happening. Can someone see an error in my XAML or explain what I'm missing?

BobTheBuilder
  • 2,455
  • 2
  • 27
  • 39

1 Answers1

2

Declare the CompositeCollection in ComboBox.Resources and use it with ItemsSource="{Binding Source={StaticResource myCompositeCollection}}" .

<UserControl x.Class="My.Application.ClientControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"                         
         xmlns:conv="clr-namespace:My.Utilities.Converters"
         Name="ClientControl">

<UserControl.Resources>
    <ResourceDictionary>
        <CollectionViewSource Key="x:ClientsCollection" />
    </ResourceDictionary>

    <conv:ClientOptions x:Key="ClientOptions" />
    <CompositeCollection x:Key="myCompositeCollection">

        <CollectionContainer Collection="{Binding Source={StaticResource ClientsCollection}, Path=[ClientNumber], Converter={StaticResource ClientOptions} />
        <ComboBoxItem>Other...</ComboBoxItem>
    </CompositeCollection>

</UserControl.Resources>

...

<ComboBox Name="Options" 
          DataContext="ClientsCollection" 
          ItemsSource="{Binding Source={StaticResource myCompositeCollection}}" />

If you declare the CompositeCollection inside the ItemsSource property in element syntax, the Binding for the CollectionContainer.Collection doesn't find its DataContext.

Inside the Resources section, Freezables like CompositeCollection inherit the DataContext of their declaring element, as if they were logical children of the element. However, this is a speciality of the Resources property and properties like ContentControl.Content or similar properties which contain the logical children of a control (and maybe a few others). If you use element syntax to set the value of a property, in general you would have to expect that property value inheritance for properties like DataContext doesn't work, and so Bindings without an explicit Source won't work, either.

hbarck
  • 2,934
  • 13
  • 16
  • Can you flesh out your answer a bit... if I move it to the Resources section and set my ItemsSource={Binding Source={StaticResource... }} how do I set the context of my CollectionContainer? – BobTheBuilder Oct 05 '12 at 17:43
  • So... my ComboBox is currently bound to a data context... my ClientsCollection; my ComboBox.ItemsSource is bound to a list of options which will change depending on the currently selected client within my ClientsCollection. Where do I define this relationship [the context]? In the resources or the combobox? Can you post a code snippet to clarify? – BobTheBuilder Oct 05 '12 at 18:03
  • Well, editing your code, I found some strange things. Are you sure the first example is working? Normally DataContext="ClientsCollection" should result in the literal string "ClientsCollection"... I found that I had to use the UserControl's Resources section, since I can't use the resource in ComboBox.ItemsSource when it is not declared before it. However, what I wrote still holds... – hbarck Oct 05 '12 at 18:18
  • Thank you, that code snippet was awesome. Just what I needed :D – BobTheBuilder Oct 05 '12 at 18:46