The combobox binding below works if I specify the ancestor, but otherwise not. Why doesn’t it work if I don’t specify the ancestor?
<wpftoolkit:DataGrid Grid.Row="4" Grid.Column="1" Grid.ColumnSpan="2"
Margin="5"
BorderBrush="#A6A6A6"
BorderThickness="1"
ItemsSource="{Binding DebitListing}"
AutoGenerateColumns="False"
SelectionMode="Single">
<wpftoolkit:DataGrid.Columns>
<wpftoolkit:DataGridComboBoxColumn
Header="{Resx ResxName=MyBooks.Properties.Strings, Key=PartyListing_Party_Label}"
SelectedItemBinding="{Binding Party, ValidatesOnDataErrors=True}"
DisplayMemberPath="Name">
<wpftoolkit:DataGridComboBoxColumn.ElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding Path=DataContext.CreditedAccounts, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" />
</Style>
</wpftoolkit:DataGridComboBoxColumn.ElementStyle>
<wpftoolkit:DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding Path=DataContext.CreditedAccounts, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" />
</Style>
</wpftoolkit:DataGridComboBoxColumn.EditingElementStyle>
</wpftoolkit:DataGridComboBoxColumn>
<wpftoolkit:DataGridTextColumn
Header="{Resx ResxName=MyBooks.Properties.Strings, Key=PartyListing_Amount_Label}"
Binding="{Binding Amount, ValidatesOnDataErrors=True}"/>
</wpftoolkit:DataGrid.Columns>
</wpftoolkit:DataGrid>
The reason you need to reference the ancestor from which to get your desired DataContext is because the
wpftoolkitchanges the datacontext on its rendered child elements. You’ll find that this is true of almost all ListView/DataGrid controls – the child element DataContext is changed to reference the collection item the current row or column is representing. If you want something in the Template or Style of those child elements to be based on a property off the control’s DataContext, you need to useRelativeSource Ancestorto get to it.I understand that this is confusing, since in basic XAML, child elements always automatically inherit the data context of their parent element, but the DataContext is just like any other DependencyProperty, and complex controls can set it differently as they see fit.
You can simplify your syntax if you like by giving your parent control (or whatever element the DataContext is set on) a name, like
x:Name='ControlRoot'. Then when you need to get back to your root datacontext, you need only go: