Search code examples
wpfxamlmvvmdatagridwpfdatagrid

Binding to DataGrid.DataTemplate


I am trying to set up a datagrid to have a details row. The DataGrid binds correctly and shows my rows. Problem is that the text for my details row does not show up when I click on a row. I've tried binding my details row with a relative source and without it. Can someone help?

<DataGrid ItemsSource="{Binding MyObservableCollection}" SelectedItem="{Binding MySelectedItem}">
<DataGrid.Columns>
    ... Defined columns
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
    <DataTemplate>
        <TextBlock Text="{Binding MyDetailsText, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
    </DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>

ViewModel:

private string myDetailsText;
private TestResultsModel mySelectedItem = null;
private ObservableCollection<TestResultsModel> myObservableCollection = new ObservableCollection<TestResultsModel>();

public ObservableCollection<TestResultsModel> MyObservableCollection
{
    get
    {
        return this.myObservableCollection ;
    }

    set
    {
        this.myObservableCollection = value;

        this.NotifyPropertyChanged(m => m.MyObservableCollection);
    }
}

public TestResultsModel MySelectedItem
{
    get
    {
        return this.mySelectedItem;
    }

    set
    {
        this.mySelectedItem= value;

        this.NotifyPropertyChanged(m => m.MySelectedItem);

        if (value != null && value.Details != null)
            {
                this.MyDetailsText= value.Details.MyDetailsObj.MyDetailsText;
            }
        }
    }
}

public string MyDetailsText
{
    get
    {
        return this.myDetailsText;
    }

    set
    {
        this.myDetailsText= value;

        this.NotifyPropertyChanged(m => m.MyDetailsText);
    }
}

Solution

  • The code you present is unecessarily jumping through hoops to get to the data. The Row template has access to the row instance object in question (which will actually be the same as the selected).

    You should simply bind to MyDetailsText such as

    Text="{Binding MyDetailsText}"
    

    Here is an example which demonstrates the process:

    <Window.Resources>
        <model:People x:Key="People">
            <model:Person First="Joe"   Last="Smith"   Phone="303-555 5555" />
            <model:Person First="Mary"  Last="Johnson" Phone="720-555 5555" />
            <model:Person First="Frank" Last="Wright"  Phone="202-555 5555" />
        </model:People>
    </Window.Resources>
    <DataGrid AutoGenerateColumns="False"
              ItemsSource="{StaticResource People}">
        <DataGrid.Columns>
            <DataGridTextColumn Header="First" Binding="{Binding First}" />
            <DataGridTextColumn Header="The Name" Binding="{Binding Last}" />
            <DataGridTextColumn Header="Phone Number" Binding="{Binding Phone}"/>
        </DataGrid.Columns>
        <DataGrid.RowDetailsTemplate>
           <DataTemplate>
               <TextBlock Text="{Binding Phone}" />
           </DataTemplate>
        </DataGrid.RowDetailsTemplate>
    </DataGrid>
    

    Here is the result:

    enter image description here