1
votes

I have a DataGrid bound to a collection of Employees. Employee class has an EmployeeCountry of type Country. Country type consists of CountryId and CountryName.

I have the following XAML:

     <DataGrid ItemsSource="{Binding EmployeeList}" CanUserAddRows="True">
            <DataGrid.Columns>
                <DataGridTemplateColumn Header="CountryCombo2">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox ItemsSource="{Binding Path=DataContext.CountryList, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" 
                                      DisplayMemberPath="CountryName" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>

The EmployeeList and CountryList are ObservableCollection properties on the ViewModel which is the DataContext for the Window containing the DataGrid. I am able to get the ComboBox populate with the CountryList.

Problem: I need to figure out how to set other properties of the ComboBox such as SelectedValuePath, SelectedItem, etc., so that each row of the DataGrid is correctly displaying the appropriate EmployeeCountry in the ComboBox. If the EmployeeCountry property of the Employee is NULL, then the ComboBox should have no item selected.

Update : I am also not able to add a new row to the DataGrid even though the CanUserAddRows property is set to true.

2
Was able to solve my problem from [this answer][1]. [1]: stackoverflow.com/questions/7088284/…Lucifer

2 Answers

2
votes

I was able to resolve my concern using the question mentioned in one of my comments. Just posting the XAML that helped get it work:

 <DataGrid ItemsSource="{Binding EmployeeList}" CanUserAddRows="True" AutoGenerateColumns="False" Margin="0,0,0,90">
        <DataGrid.Columns>
            <DataGridTemplateColumn Header="CountryCombo2">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ComboBox ItemsSource="{Binding Path=DataContext.CountryList, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" 
                                      DisplayMemberPath="CountryName" 
                                      SelectedItem="{Binding EmployeeCountry, Mode=TwoWay}"
                                      SelectedValue="{Binding EmployeeCountry.CountryId}"
                                      SelectedValuePath="CountryId" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
1
votes

I would do something like this

 <ComboBox SelectedValuePath="CountryName" SelectedItem="{Binding Country}"  ItemsSource="{Binding Path=DataContext.CountryList, RelativeSource={RelativeSource AncestorType={x:Type Window}}}">

And just to show you what I gave you works, I am putting the full code written.

public class Employees :INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }

    private string _name;
    public string Name
    {
        get
        {
            return _name; 
        }

        set
        {
            if (_name == value)
                return;
            _name = value;
            OnPropertyChanged();
        }
    }

    private Country _employeeCountry;
    public Country EmployeeCountry
    {
        get
        {
            return _employeeCountry;
        }

        set
        {
            if (_employeeCountry == value)
                return;
            _employeeCountry = value;
            OnPropertyChanged();
        }
    }
}

public class Country
{
    private string _name;
    public string Name
    {
        get
        {
            return _name;
        }

        set
        {
            if (_name == value)
                return;
            _name = value;
        }
    }
}

private static ObservableCollection<Country> _countryList = new ObservableCollection<Country>(new []{ new Country{Name="US"}, new Country{Name="UK"}});

public ObservableCollection<Country> CountryList
{
    get
    {
        return _countryList;
    }
}

private ObservableCollection<Employees> _employeeList = new ObservableCollection<Employees>(new[] { new Employees { Name = "Ty", EmployeeCountry = _countryList.First() }, new Employees { Name = "Dude" } });

public ObservableCollection<Employees> EmployeeList
{
    get
    {
        return _employeeList;
    }
}

And the Xaml

<DataGrid ItemsSource="{Binding EmployeeList}" CanUserAddRows="True">
        <DataGrid.Columns>
            <DataGridTemplateColumn Header="CountryCombo2">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ComboBox ItemsSource="{Binding Path=CountryList, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" DisplayMemberPath="Name"
                                 SelectedValuePath="Name" SelectedItem="{Binding EmployeeCountry}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>