How to change datacontext for DataGridComboBoxColumn to a specific class?

John P Source

I'm totally new at WPF and I'm stuck with the bellow situation:

 class Person{
    string Name;
    List<Address> ListAddresses;
 }

I have a DataGrid with ItemsSource as an ObservableCollection<Person>. This collection is in MainViewModel class.

I want to create a DataGridComboBoxColumn with the addresses.

<DataGrid ItemsSource="{Binding Persons, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
   <DataGrid.Columns>   
      <DataGridComboBoxColumn ItemsSource="{Binding Path=ListAddresses, RelativeSource={RelativeSource Mode=FindAncestor,
         AncestorType={x:Type local:Person}}}">
      </DataGridComboBoxColumn>      
   </DataGrid.Columns>
</DataGrid>

I receive the following error:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='PersonApp.UL.ViewModels.Person', AncestorLevel='1''. BindingExpression:Path=ListAddresses; DataItem=null; target element is 'DataGridComboBoxColumn' (HashCode=11440639); target property is 'ItemsSource' (type 'IEnumerable')

c#wpf

Answers

answered 1 year ago Kacper Stachowski #1

DataGridComboBoxColumn is going to cause you many problems. Try this:

    <DataGridTemplateColumn Header="Something"
                            SortMemberPath="[SelectedAddress].[property from Address class]">
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <ComboBox ItemsSource="{Binding ListAddresses}"
                          SelectedItem="{Binding SelectedAddress, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                          SelectedValuePath="[SelectedAddress].[property from Address class]"
                          DisplayMemberPath="[property from Address class (like Name)]" />
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>

You should also include SelectedAddress property in your Person class, to store which Address is selected in the ComboBox.

Binding to property that is inside your ItemsSource scope (which in this case is what you bind to DataGrid) does not require RelativeSource binding, that's why you are getting an error. RelativeSource is required in case you set your DataGrid.ItemsSource to for example PeopleList and you want to bind your (that is inside this DataGrid) ComboBox.ItemsSource to a property that is in your ViewModel, but NOT inside your PeopleList.

Another thing for binding to ComboBox is if you bind ItemsSource to a collection of objects other than strings, you have to set DisplayMemberPath to a property in your object, in order to make the control display the right caption. So for example if you are binding object Car and it has a string type property called Name, you should set DisplayMemberPath to Name in order to make your control display list of Car.Names (selecting one will still result in selecting the whole object, not just the Name property).

comments powered by Disqus