Search code examples
wpfdatagridcomboboxcolumn

DataGridComboBoxColumn is empty


My DataGridComboBoxColumn does not show any data. It's empty. I have no problem to fill a ComboBox, but DataGridComboBoxColumn doesn't work.
.NetFramework 4.6.1

Model:

public class Address
{
    public string Firstname { get; set; }
    public string Lastname { get; set; }
    public string Country { get; set; }
}

ViewModel:

public class AddressViewModel
{
    public AddressViewModel()
    {
        LoadAdresses();
        LoadCountries();
    }

    public List<Address> AddressList { get; set; }
    public List<string> CountryList { get; set; }


    private void LoadAdresses()
    {
        AddressList = new List<Model.Address>();
        AddressList.Add(new Model.Address(){ Firstname = "Peter", Lastname = "R.", Country = "A" });
        AddressList.Add(new Model.Address(){ Firstname = "Tom", Lastname = "A.", Country = "A" });
        AddressList.Add(new Model.Address(){ Firstname = "Sam", Lastname = "F.", Country = "A" });
    }

    private void LoadCountries()
    {
        CountryList = new List<string>();
        CountryList.Add("A");
        CountryList.Add("D");
        CountryList.Add("CH");
        CountryList.Add("GB");
        CountryList.Add("F");
    }
}

View:

<Window.DataContext>
    <vm:AddressViewModel/>
</Window.DataContext>

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <DataGrid x:Name="AddressDataGrid" Grid.Row="0" ItemsSource="{Binding AddressList}" AutoGenerateColumns="False" >
        <DataGrid.Columns>
            <DataGridTextColumn Header="Firstname" Binding="{Binding Firstname}" />               
            <DataGridTextColumn Header="Lastname" Binding="{Binding Lastname}" />
            <DataGridComboBoxColumn Header="Country" 
                        SelectedItemBinding="{Binding Country}"
                        ItemsSource="{Binding CountryList}"/>
        </DataGrid.Columns>
    </DataGrid>

    <!--This ComboBox works-->
    <ComboBox Grid.Row="1" ItemsSource="{Binding CountryList}"/>
</Grid>

What is the reason for this behaviour?


Solution

  • You are binding to a property CountryList in your DataGridComboBoxColumn. But this property is not in your class Address; it's in your class AddressViewModel. Thats why you don't see anything in your ComboBox; the binding is not valid.

    Each entry in your List<Address> AddressList stands for one line in your DataGrid and you can access each property of Address in each line with the 'normal' binding {Binding Property}. But you want to access a property which is in the class that holds the List<Address> AddressList. That's why you have to use a different way to bind. Two ways are possible:

    • RelativeSource binding
    • binding via ElementName

    This should work for you

    <DataGridComboBoxColumn Header="Country"
                            SelectedItemBinding="{Binding Country}">
        <DataGridComboBoxColumn.ElementStyle>
            <Style TargetType="{x:Type ComboBox}">
                <Setter Property="ItemsSource"
                        Value="{Binding Path=DataContext.CountryList, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
            </Style>
        </DataGridComboBoxColumn.ElementStyle>
        <DataGridComboBoxColumn.EditingElementStyle>
            <Style TargetType="{x:Type ComboBox}">
                <Setter Property="ItemsSource"
                        Value="{Binding Path=DataContext.CountryList, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
            </Style>
        </DataGridComboBoxColumn.EditingElementStyle>
    </DataGridComboBoxColumn>
    

    And just a hint: if you bind collections to your view use ObservableCollection instead of List to keep your view up to date.