I'm new to WPF. I have a StackPanel which contains multiple comboboxes with the ItemSource (set in the StackPanel's style) from a View (CaSupplierColumns
) in SQL Server (Visual Studio created the link automatically which I dragged ordersDataSet
from the Data Source panel). No problem with this.
Issue arises when I use CompositeCollection
in order to add a custom value to one of the comboboxes (Manufacturer
), all values show correctly and the added item appears too - but blank. The added item appears as a blank option in the combobox.
The culprit I discovered is the DisplayMemberPath
set to Columns
(which is the column header's name in the database view), when I set the DisplayMemberPath
to null for this combobox, the added item appears indeed correctly, but the other values in the combobox appear as System.Data.DataRowView
.
How can I have two different DisplayMemberPath
s in one CompositeCollection? Or perhaps is there a different way to do it?
Here's my current XAML (stripped to leave the key parts):
<Window.Resources>
<local:OrdersDataSet x:Key="ordersDataSet" />
<CollectionViewSource x:Key="caSupplierColumnsViewSource" Source="{Binding CaSupplierColumns, Source={StaticResource ordersDataSet}}" />
</Window.Resources>
<StackPanel Name="MapFields" DataContext="{StaticResource caSupplierColumnsViewSource}">
<StackPanel.Resources>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding}" />
<Setter Property="DisplayMemberPath" Value="Columns" />
<Setter Property="SelectedValuePath" Value="Columns" />
<Setter Property="IsSynchronizedWithCurrentItem" Value="False" />
</Style>
</StackPanel.Resources>
...
<ComboBox Name="MfrPartNo" />
...
<ComboBox Name="Manufacturer">
<ComboBox.ItemsSource>
<CompositeCollection>
<CollectionContainer Collection="{Binding Source={StaticResource ResourceKey=caSupplierColumnsViewSource}}" />
<ListBoxItem>Another option</ListBoxItem>
</CompositeCollection>
</ComboBox.ItemsSource>
</ComboBox>
</StackPanel>
I would create implicit DataTemplates for the various types in the collections, and I'd put them in that same StackPanel.Resources
where you've got the implicit ComboBox
Style. You'll have to get rid of the DisplayMemberPath
attribute, because that'll prevent the implicit DataTemplates from being applied.
DisplayMemberPath
isn't a very powerful feature; you switch to DataTemplates when the going gets weird. Throwing a heterogeneous bunch of stuff in a ComboBox
is one of the cool things you can do with WPF, but you'll still have to do some work to get much use out of it.
SelectedValuePath
is going to be of limited use here as well, for obvious reasons. You might have to start binding SelectedItem
to a viewmodel property of type Object
and doing some fiddling in the setter there.
<StackPanel.Resources>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding}" />
<Setter Property="SelectedValuePath" Value="Columns" />
<Setter Property="IsSynchronizedWithCurrentItem" Value="False" />
</Style>
<DataTemplate DataType="{x:Type Manufacturer}">
<!-- I'm assuming Manufacturer has a Name property; change as needed -->
<TextBlock Text="{Binding Name}" />
</DataTemplate>
<DataTemplate
xmlns:sysdata="clr-namespace:System.Data;assembly=System.Data"
DataType="{x:Type sysdata:DataRowView}">
<TextBlock Text="{Binding Columns}" />
</DataTemplate>
<!-- Etc. -->
</StackPanel.Resources>