Binding ItemsSource of a ComboBoxColumn in WPF DataGrid Binding ItemsSource of a ComboBoxColumn in WPF DataGrid wpf wpf

Binding ItemsSource of a ComboBoxColumn in WPF DataGrid


Pls, check if DataGridComboBoxColumn xaml below would work for you:

<DataGridComboBoxColumn     SelectedValueBinding="{Binding CompanyID}"     DisplayMemberPath="Name"     SelectedValuePath="ID">    <DataGridComboBoxColumn.ElementStyle>        <Style TargetType="{x:Type ComboBox}">            <Setter Property="ItemsSource" Value="{Binding Path=DataContext.CompanyItems, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />        </Style>    </DataGridComboBoxColumn.ElementStyle>    <DataGridComboBoxColumn.EditingElementStyle>        <Style TargetType="{x:Type ComboBox}">            <Setter Property="ItemsSource" Value="{Binding Path=DataContext.CompanyItems, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />        </Style>    </DataGridComboBoxColumn.EditingElementStyle></DataGridComboBoxColumn>

Here you can find another solution for the problem you're facing: Using combo boxes with the WPF DataGrid


The documentation on MSDN about the ItemsSource of the DataGridComboBoxColumn says that only static resources, static code or inline collections of combobox items can be bound to the ItemsSource:

To populate the drop-down list, first set the ItemsSource property for the ComboBox by using one of the following options:

  • A static resource. For more information, see StaticResource Markup Extension.
  • An x:Static code entity. For more information, see x:Static Markup Extension.
  • An inline collection of ComboBoxItem types.

Binding to a DataContext's property is not possible if I understand that correctly.

And indeed: When I make CompanyItems a static property in ViewModel ...

public static ObservableCollection<CompanyItem> CompanyItems { get; set; }

... add the namespace where the ViewModel is located to the window ...

xmlns:vm="clr-namespace:DataGridComboBoxColumnApp"

... and change the binding to ...

<DataGridComboBoxColumn    ItemsSource="{Binding Source={x:Static vm:ViewModel.CompanyItems}}"     DisplayMemberPath="Name"    SelectedValuePath="ID"    SelectedValueBinding="{Binding CompanyID}" />

... then it works. But having the ItemsSource as a static property might be sometimes OK, but it is not always what I want.


The correct solution seems to be:

<Window.Resources>    <CollectionViewSource x:Key="ItemsCVS" Source="{Binding MyItems}" /></Window.Resources><!-- ... --><DataGrid ItemsSource="{Binding MyRecords}">    <DataGridComboBoxColumn Header="Column With Predefined Values"                            ItemsSource="{Binding Source={StaticResource ItemsCVS}}"                            SelectedValueBinding="{Binding MyItemId}"                            SelectedValuePath="Id"                            DisplayMemberPath="StatusCode" /></DataGrid>

The layout above works perfectly fine for me, and should work for others. This design choice also makes sense, though it isn't very well explained anywhere. But if you have a data column with predefined values, those values typically don't change during run-time. So creating a CollectionViewSource and initializing the data once makes sense. It also gets rid of the longer bindings to find an ancestor and bind on it's data context (which always felt wrong to me).

I am leaving this here for anyone else who struggled with this binding, and wondered if there was a better way (As this page is obviously still coming up in search results, that's how I got here).