2

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.

Lucifer
  • 2,317
  • 9
  • 43
  • 67
  • Was able to solve my problem from [this answer][1]. [1]: http://stackoverflow.com/questions/7088284/wpf-datagridtemplatecolumn-with-combobox-binding-mvvm-pattern?rq=1 – Lucifer Mar 11 '14 at 13:13

2 Answers2

2

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>
Lucifer
  • 2,317
  • 9
  • 43
  • 67
1

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>
TYY
  • 2,702
  • 1
  • 13
  • 14
  • 1
    I did not just post the code, I gave you something that I actually use. Before you say it does not work and down vote show the structure of your object. Be smart about people trying to help you as far as I see I am the only one so far who answered this question, while people are passing it by. – TYY Mar 11 '14 at 11:43
  • @TTY, I totally accept your defense, and also accept your claim that I acted in haste to down vote your answer. However, I assumed that I was pretty clear in expressing my question and that it was sufficient for the reader to understand my problem. I give you back your 2 rep points. I was able to solve my problem from another question posted. I will delete my question after giving out the answer. Thanks for your assistance. – Lucifer Mar 11 '14 at 13:11
  • @TTY, could you help me in solving my concern relating to the update to my question - about adding a new row to the DataGrid. – Lucifer Mar 11 '14 at 13:25
  • You don't have a default constructor in your Employee class which is why it doesn't allow you to add rows. – TYY Mar 11 '14 at 16:13
  • Even though I added a default constructor, the problem persists. I have described my problem in a new question for the DataGrid issue : http://stackoverflow.com/questions/22330173/editable-datagrid-canuseraddrows-true-not-working – Lucifer Mar 12 '14 at 15:29