问题
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?
回答1:
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.
回答2:
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>
回答3:
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>
来源:https://stackoverflow.com/questions/4726777/binding-a-combobox-control-to-a-separate-source-within-a-datagrid