2

Im attempting to use a ComboBox within a DataGrid which will allow the user to select a value coming from a different table. Im using a ViewModel class as the DataContext and this contains an ObservableCollection for Terminals and another for TerminalTypes.

The binding on the grid is fine, all the rows are populated and the DataGridTextColumns all show the correct data, my ComboBox however is empty.

I know that the ObservableCollection Im attempting to bind to has been populated and if I move the ComboBox outside of the DataGrid it works as expected.

<my:DataGrid Name="MenuDetailGrid" AutoGenerateColumns="False" ItemsSource="{Binding Terminals}">
    <my:DataGrid.Columns>
        <my:DataGridTextColumn Header="Terminal Type ID" Binding="{Binding TERMINAL_TYPE_ID}" IsReadOnly="True" />
        <my:DataGridTemplateColumn Header="Terminal Type">
            <my:DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <ComboBox DisplayMemberPath="TTYPE_NAME" SelectedValuePath="TERMINAL_TYPE"
                              SelectedValue="{Binding TERMINAL_TYPE_ID}" 
                              ItemsSource="{Binding TerminalTypes}" />

                </DataTemplate>
            </my:DataGridTemplateColumn.CellTemplate>
        </my:DataGridTemplateColumn>

Obviously the binding behaviour is different on the ComboBox when part of the DataGrid but Im a bit stumped as to why?

Can someone please help me understand what I am doing wrong?

Andrew
  • 885
  • 1
  • 12
  • 22

3 Answers3

4

The binding behaviour is the same. However is the DataContext in a DataTemplate set by the ItemsControl to current item and this is in your case a member of the Terminals-collection. Therefore, the TerminalTypes-collection could not be found (unless you implement it also on your item).

What you can do is to use a relative source in your Binding. With this, you can navigate to the DataGrid's DataContext and then access your TerminalTypes-Collection:

<ComboBox DisplayMemberPath="TTYPE_NAME"
    SelectedValuePath="TERMINAL_TYPE"
    SelectedValue="{Binding TERMINAL_TYPE_ID}"
    ItemsSource="{Binding DataContext.TerminalTypes,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=DataGrid}" /> 

Hope this helped. Make a comment if not.

HCL
  • 36,053
  • 27
  • 163
  • 213
  • I think the OP is already using MVVM since he mentions that it the data is on the ViewModel :-) – Goblin Jan 18 '11 at 19:42
  • This worked, I guess it was the DataContext.TerminalTypes and RelativeSource that did the trick. – Andrew Jan 18 '11 at 21:47
  • Goodness gracious why is it so complicated? Took me hours to find an answer that actually worked. Thanks! – joniba Mar 10 '11 at 19:10
  • Thanks a lot, I tried finding several RelativeSources higher than DataGrid, until I hit your answer, and tried Datagrid. It worked!! thank you. – Adarsha Apr 14 '12 at 01:13
1

You should look at this answer from Aran Mulholland.

It has a nice sample for using a DataGridComboBoxColumn

Adapted this article for your XAML

<my:DataGridComboBoxColumn SelectedValueBinding="{Binding TERMINAL_TYPE_ID}"
  SelectedValuePath="TERMINAL_TYPE_ID"
  DisplayMemberPath="TERMINAL_TYPE"
  Header="Terminal Type"
  ItemsSource="{Binding TerminalTypes}" />

</my:DataGridComboBoxColumn>
Community
  • 1
  • 1
Conrad Frix
  • 51,984
  • 12
  • 96
  • 155
  • That looks exactly like it should work and yet it doesn't, I must be missing something obvious here. – Andrew Jan 18 '11 at 17:40
0

This is what I ended up with in my little test project, Ill be adapting this for use in the proper code.

<Grid>
    <Controls:DataGrid Name="MenuDetailGrid" AutoGenerateColumns="False" ItemsSource="{Binding Terminals}">
        <Controls:DataGrid.Columns>
            <Controls:DataGridTemplateColumn Header="SomeHeader">
                <Controls:DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding TTYPE_NAME}" />
                    </DataTemplate>
                </Controls:DataGridTemplateColumn.CellTemplate>
                <Controls:DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <ComboBox DisplayMemberPath="TTYPE_NAME"
                            SelectedValuePath="TERMINAL_TYPE_ID"
                            SelectedValue="{Binding TERMINAL_TYPE_ID}"
                            ItemsSource="{Binding DataContext.TerminalTypes,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=Controls:DataGrid}}" />
                    </DataTemplate>
                </Controls:DataGridTemplateColumn.CellEditingTemplate>
            </Controls:DataGridTemplateColumn>
        </Controls:DataGrid.Columns>
    </Controls:DataGrid>
</Grid>
Andrew
  • 885
  • 1
  • 12
  • 22