Search code examples
c#wpfmvvmdata-bindingcompositecollection

How to merge two sources in a Collection and show them correct in a combobox?


I have some XAML code that makes me mad. It started all with adding a dummy Item for a not referenced value.

For this I had to implement a CollectionViewSource and a CompositeCollection. Now I can't select the first Combobox Item, it appears but I cannot select it, because I set the DisplayMemberPath in XAML (I guess so). Also the separator looks not as expected.

Let me show you:


screenshot


If I don't set the XAML DisplayMemberPath, I can use the Dummy Item but the bound ones are displayed incorrect:

screenshot

XAML:

<ComboBox x:Name="G_cb_content_zuordnung" 
          Margin="165,0,0,0" 
          Grid.Row="1" 
          SelectedIndex="0"
          VerticalAlignment="Top"
          DisplayMemberPath="PartnerID"
          HorizontalAlignment="Left" 
          Width="119">
    <ComboBox.Resources>
        <CollectionViewSource x:Key="ComboCollection" Source="{Binding Path=mySelectedItem.Stammkinder}" />
    </ComboBox.Resources>
    <ComboBox.ItemsSource>
        <CompositeCollection>
            <ComboBoxItem Content="Ohne Stammnummer" Name="NoPID" />
            <Separator />
            <CollectionContainer Collection="{Binding Source={StaticResource ComboCollection}, Mode=OneWay}" />
        </CompositeCollection>
    </ComboBox.ItemsSource>
</ComboBox>

All I need is a dummy / placeholder combobox item that gets shown on top of the ObservableCollection<myClass>. Is my way of thinking wrong? Is there a smarter solution? Do I miss something in my solution?


Solution

  • Use your second approach and define a DataTemplate for the items explicitly, rather than using the DisplayMemberPath property:

    <ComboBox xmlns:o="clr-namespace:APP.GLN_Organisator.Objects">
        <ComboBox.Resources>
            <CollectionViewSource x:Key="ComboCollection"
                                  Source="{Binding Path=mySelectedItem.Stammkinder}" />
    
            <!-- Define a DataTemplate here -->
            <DataTemplate DataType="{x:Type o:ChildPartner}">
                <TextBlock Text="{Binding PartnerID}"/>
            </DataTemplate>
    
        </ComboBox.Resources>
        <ComboBox.ItemsSource>
            <CompositeCollection>
                <ComboBoxItem Content="Ohne Stammnummer" Name="NoPID" />
                <Separator />
                <CollectionContainer Collection="{Binding Source={StaticResource ComboCollection}}" />
            </CompositeCollection>
        </ComboBox.ItemsSource>
    </ComboBox>
    

    With a DataTemplate, you tell WPF how you want to display your items. If you don't provide any DataTemplate and don't set the DisplayMemberPath property value, WPF falls back to the simple ToString() call for displaying your items. That's why you see these type strings instead of your items.