views:

71

answers:

1

Question: Most code samples on the DataGridComboBox seem to use a static resource as the ItemsSource. In my use case, I'd like to provide different ItemsSources with each bound object. Can this be done?

Background: I'm trying to bind a collection of Question class objects to a WPF DataGrid, using a DataGridComboBoxColumn control. The Answer string provides the SelectedValue. I'd like the AnswerDomain list to provide the ItemsSource for each ComboBox. The AnswerDomain differs from Question to Question.

Class

public class Question
  {
    string Answer {get; set;}
    List<string> AnswerDomain {get; set;}
    //...other stuff
  }

XAML

<DataGrid ItemsSource="{Binding Path=InspectionItems}" AutoGenerateColumns="False" Name="dataGrid1" >
    <DataGrid.Columns>
        <DataGridComboBoxColumn Header="Answer Domain"
                                DisplayMemberPath="Answer"
                                SelectedValuePath="Answer"
                                ItemsSource="{Binding Path=AnswerDomain}" 
                                    >
        </DataGridComboBoxColumn>
    </DataGrid.Columns>
</DataGrid>

Problem: There are a couple problems. The key issue right now is that the ComboBoxes in each DataGrid Row aren't displaying the AnswerDomain strings. I've tried a series of XAML combinations without success. Help me Stack Overflow.

UPDATE: The selected solution below worked. After some further fumbling and by adding UpdateSourceTrigger=PropertyChanged to the SelectedItem, user changes in the combobox were then reflected back in the underlying custom object.

<DataGridTemplateColumn Header="Answer">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <ComboBox 
                ItemsSource="{Binding AnswerDomain}" 
                SelectedItem="{Binding Answer, UpdateSourceTrigger=PropertyChanged}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
+2  A: 

Your problem is that the display member path isn't Answer because there is no "Answer" property off of a string. I never use the DataGridComboBoxColumn, it doesn't seem natural to me, too much like the old win forms way. Try the below instead. BUT MAKE SURE YOU IMPLEMENT INotifyPropertyChanged on your Question Class, and fire the appropriate events.

<DataGridTemplateColumn>
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <ComboBox ItemsSource="{Binding AnswerDomain}" SelectedItem="{Binding Answer}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn> 

Here is how your Question class should look:

public class Question : INotifyPropertyChanged
{
    private string m_Answer;
    public string Answer
    {
        get { return m_Answer; }
        set
        {
            if (m_Answer != value)
            {
                m_Answer = value;
                FirePropertyChanged("Answer");
            }
        }
    }

    private List<string> m_AnswerDomain;
    public List<string> AnswerDomain
    {
        get { return m_AnswerDomain; }
        set
        {
            if (m_AnswerDomain != value)
            {
                m_AnswerDomain = value;
                FirePropertyChanged("AnswerDomain");
            }
        }
    }


    [field: NonSerialized]
    public event PropertyChangedEventHandler PropertyChanged;

    private void FirePropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }


}
viggity
Thanks, @viggity. That does the trick. Strangely enough, even with INPC implemented, I'm having some trouble getting UI changes to reflect back in the bound object collection but I guess that's a different problem. Thanks again. -Wen
Rox Wen