as default.kramer said, you need to remove the RelativeSource
from your bindings for the SelectedItem
and SelectedValue
like this (notice that you should add Mode=TwoWay
to your binding so that the change in the combobox is reflected in your model).
<DataGridTemplateColumn Header="House Owner">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox
ItemsSource="{Binding Path=DataContext.Owners, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
DisplayMemberPath="Name"
SelectedItem="{Binding HouseOwner, Mode=TwoWay}"
SelectedValue="{Binding HouseOwner.ID}"
SelectedValuePath="ID"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
However, unlike he said, you don't have to remove the binding for the SelectedValue
. In fact, if you remove it, it won't work (both SelectedValue
and SelectedValuePath
should be set here, as you've done), because that's what's allowing the binding mechanism to identify the selection from the combobox to the DataGrid's HouseOwner
property.
SelectedValue
/SelectedValuePath
combination is very interesting. SelectedValuePath
tells the databinding that the ID
property of the Owner
object currently selected represents its value, SelectedValue
tells it that that value should be bound to the HouseOwner.ID
which is the selected object on the DataGrid.
Therefore, if you remove those binding, the only thing the databinding mechanism will know is "what object is selected", and to make the correspondence between the selected item in the ComboBox and the HouseOwner
property on the selected item in the DataGrid, they have to be "the same object reference". Meaning that, for example, the following wouldn't work:
Owners = new ObservableCollection<Owner>
{
new Owner {ID = 1, Name = "Abdou"},
new Owner {ID = 2, Name = "Moumen"}
};
Houses = new ObservableCollection<House>
{
new House {ID = 1, HouseOwner = new Owner {ID = 1, Name = "Abdou" }},
new House {ID = 2, HouseOwner = new Owner {ID = 2, Name = "Moumen"}}
};
(notice that the "HouseOwners" of the Houses collection are different (new) from the ones in the Owners collection). However, the following would work:
Owners = new ObservableCollection<Owner>
{
new Owner {ID = 1, Name = "Abdou"},
new Owner {ID = 2, Name = "Moumen"}
};
Houses = new ObservableCollection<House>
{
new House {ID = 1, HouseOwner = Owners[0]},
new House {ID = 2, HouseOwner = Owners[1]}
};
Hope this helps :)
Update: in the second case, you can get the same result without having the references being the same by overriding Equals on the Owner
class (naturally, since it's used to compare the objects in the first place). (thanks to @RJ Lohan for noting this in the comments below)