Search code examples
wpfmvvmdata-bindingdatagrid

WPF DataGrid - RowDetails DataContext


Background

I have the following DataGrid that has two columns for a Description and a Status. These are bound to an ObservableCollection<RowViewModel> called RowViewModels which is passed as the ItemsSource on the DataGrid. When selected, there are row details that become visible. For the sake of this example, there are two text boxes in the details that are bound to the same properties as the DataGrid.

Problem

I am getting binding errors on the RowDetails when the row is selected and the details are visible. Inspecting the visual tree and the binding error itself, it is showing that the DataContext for the RowDetails is DataTemplate rather than the DataContext of the DataGrid row. It does not seem like the DataContext of the selected row is propagating down to the RowDetails. The DataGrid control is as follows, with the implementation of this control following that:

Please note that there is a VM for the grid itself that has the RowViewModels property, as previously mentioned

DataGridControl

<DataGrid ItemsSource="{Binding RowViewModels}"
          RowDetailsVisibilityMode="VisibleWhenSelected">
    
    <DataGrid.Columns>
        <DataGridTextColumn Header="Description" Binding="{Binding Description}"
                            Width="auto"
                            IsReadOnly="True"/>
        <DataGridTextColumn Header="Status" Binding="{Binding Status}"
                            Width="auto"
                            IsReadOnly="True"/>
    </DataGrid.Columns>


<DataGrid.RowDetailsTemplate>
    <DataTemplate>
            <Border Width="auto"
                    BorderThickness="0 0 0 1"
                    DataContext="{Binding}">
            
                <StackPanel Orientation="Vertical"
                            HorizontalAlignment="Left"
                            Height="auto"
                            Width="auto">
                        <TextBlock Text="{Binding Description}"/>
                        <TextBlock Text="{Binding Status}"/>
                </StackPanel>
            </Border>
        </DataTemplate>
    </DataGrid.RowDetailsTemplate>
    
</DataGrid>

Implementation

        <controls:MyDataGrid
            DataContext="{Binding DataGridViewModel}"
            Grid.Row="2"
            Height="auto"
            Width="auto"
            Margin="16 8 16 16"/>

Question

How can the DataContext of the row propagate down to the RowDetails so that the binding can work properly?


Solution

  • Fixed it by explicitly defining the DataContext of the Border within the DataTemplate:

    <DataGrid.RowDetailsTemplate>
    <DataTemplate>
            <Border Width="auto"
                    BorderThickness="0 0 0 1"
                    DataContext="{Binding DataContext,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGridRow}}}">