title: Can't save add or delete rows in DataGrid inside RowDetailsTemplate of another DataGrid (WPF)
body: <p>I’m writing an HR safety tracking app using WPF and Entity Framework where I want to display and edit a grid of safety incidents, and under each selected incident would be a grid of months during which hours were lost due to the incident.  This means a DataGrid for the hours inside the RowDetailsTemplate of a DataGrid for the incidents.</p>
  
  <p>I can currently save changes I make to existing hours rows but I can’t save the additions or deletions to this inner DataGrid.  My relevant model code:</p>
  
  <pre><code>[Table("hr.safety_incident")]
  public partial class SafetyIncident
  {
      [Key]
      [Column(TypeName = "numeric")]
      [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
      public decimal incident_id { get; set; }
  
      [Column(TypeName = "datetime2")]
      public DateTime incident_date { get; set; }
  
      [Required]
      [StringLength(30)]
      public string incident_type { get; set; }
  }
  
  // EDIT: forgot this part of the class
  public partial class SafetyIncident    // In another file
  {
      protected ObservableCollection&lt;SafetyHours&gt; _lostHoursDetails;
  
      [NotMapped]
      public ObservableCollection&lt;SafetyHours&gt; LostHoursDetails
      {
          get { return _lostHoursDetails; }
          set
          {
              if (_lostHoursDetails != value)
              {
                  _lostHoursDetails = value;
              }
          }
      }
  }
  
  [Table("hr.safety_hours")]
  public partial class SafetyHours
  {
      [Key]
      [Column(TypeName = "numeric")]
      [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
      public decimal safety_hours_id { get; set; }
  
      [Column(TypeName = "numeric")]
      public decimal incident_id { get; set; }
  
      [Column(TypeName = "datetime2")]
      public DateTime safety_hours_date { get; set; }
  
      [Column(TypeName = "numeric")]
      public decimal restricted_hours { get; set; }
  
      [Column(TypeName = "numeric")]
      public decimal lost_hours { get; set; }
  }
  </code></pre>
  
  <p>Relevant XAML:</p>
  
  <p>
      
  </p>
  
  <pre><code>&lt;DataGrid x:Name="dtgAllIncidents" AutoGenerateColumns="False" 
          ItemsSource="{Binding Source={StaticResource safetyIncidentViewSource}}" 
          RowDetailsVisibilityMode="VisibleWhenSelected"&gt;
      &lt;DataGrid.Columns&gt;
          &lt;DataGridTemplateColumn x:Name="incident_dateColumn" Header="Incident Date" Width="110" SortMemberPath="incident_date"&gt;
              &lt;DataGridTemplateColumn.CellTemplate&gt;
                  &lt;DataTemplate&gt;
                      &lt;DatePicker IsHitTestVisible="False" 
                          SelectedDate="{Binding incident_date, Mode=TwoWay, NotifyOnValidationError=true, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=true}"/&gt;
                  &lt;/DataTemplate&gt;
              &lt;/DataGridTemplateColumn.CellTemplate&gt;
              &lt;DataGridTemplateColumn.CellEditingTemplate&gt;
                  &lt;DataTemplate&gt;
                      &lt;DatePicker SelectedDate="{Binding incident_date, Mode=TwoWay, NotifyOnValidationError=true, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=true}"/&gt;
                  &lt;/DataTemplate&gt;
              &lt;/DataGridTemplateColumn.CellEditingTemplate&gt;
          &lt;/DataGridTemplateColumn&gt;
          &lt;DataGridTextColumn Header="Incident Type" Binding="{Binding incident_type}"/&gt;
      &lt;/DataGrid.Columns&gt;
      &lt;DataGrid.RowDetailsTemplate&gt;
          &lt;DataTemplate&gt;
              &lt;StackPanel Orientation="Horizontal"&gt;
                  &lt;TextBlock Text="Enter data into the blank row to add lost and restricted hours.”/&gt;
                  &lt;DataGrid x:Name="dtgLostHoursDetails" ItemsSource="{Binding LostHoursDetails}" AutoGenerateColumns="False" CanUserAddRows="True" CanUserDeleteRows="True"&gt;
                      &lt;DataGrid.Columns&gt;
                          &lt;DataGridTemplateColumn x:Name="incident_dateColumn" Header="Month in Which Hours Lost"&gt;
                              &lt;DataGridTemplateColumn.CellTemplate&gt;
                                  &lt;DataTemplate&gt;
                                      &lt;DatePicker IsHitTestVisible="False"
                                              SelectedDate="{Binding safety_hours_date, Mode=TwoWay, NotifyOnValidationError=true, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=true}"/&gt;
                                  &lt;/DataTemplate&gt;
                              &lt;/DataGridTemplateColumn.CellTemplate&gt;
                              &lt;DataGridTemplateColumn.CellEditingTemplate&gt;
                                  &lt;DataTemplate&gt;
                                      &lt;DatePicker SelectedDate="{Binding safety_hours_date, Mode=TwoWay, NotifyOnValidationError=true, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=true}"/&gt;
                                  &lt;/DataTemplate&gt;
                              &lt;/DataGridTemplateColumn.CellEditingTemplate&gt;
                          &lt;/DataGridTemplateColumn&gt;
                          &lt;DataGridTextColumn Width="SizeToHeader" Header="Lost Hours" Binding="{Binding lost_hours}"/&gt;
                          &lt;DataGridTextColumn Width="SizeToHeader" Header="Restricted Hours" Binding="{Binding restricted_hours}"/&gt;
                      &lt;/DataGrid.Columns&gt;
                  &lt;/DataGrid&gt;
              &lt;/StackPanel&gt;
          &lt;/DataTemplate&gt;
      &lt;/DataGrid.RowDetailsTemplate&gt;
  &lt;/DataGrid&gt;
  </code></pre>
  
  <p>Relevant code-behind:</p>
  
  <pre><code>private ObservableCollection&lt;SafetyIncident&gt; _incidents;
  private SafetyIncidentsViewModel _incidentsVM = new SafetyIncidentsViewModel();
  
  private void mniIncidents_Click(object sender, RoutedEventArgs e)
  {
      CollectionViewSource safetyIncidentViewSource = ((CollectionViewSource)this.FindResource("safetyIncidentViewSource")));
      _incidents = _incidentsVM.GetIncidents();
      safetyIncidentViewSource.Source = _incidents;
  }
  private void btnSaveIncidents_Click(object sender, RoutedEventArgs e)
  {
      _incidentsVM.SaveChanges();
      dtgAllIncidents.Items.Refresh();
  }
  </code></pre>
  
  <p>...</p>
  
  <pre><code>public class SafetyIncidentsViewModel
  {
      private Corp_DB _context = new Corp_DB();
  
      public ObservableCollection&lt;SafetyIncident&gt; GetIncidents()
      {
          ObservableCollection&lt;SafetyIncident&gt; results = null;
          LoadSafetyIncidents();
          results = _context.safety_incident.Local;
          return results;
      }
  
      private void LoadSafetyIncidents()
      {
          _context.safety_incident.OrderBy(si =&gt; si.incident_date).Load();
          _context.safety_hours.Load();
          foreach (var i in _context.safety_incident)
          {
              var lostHours = new ObservableCollection&lt;SafetyHours&gt;();
              foreach (var h in _context.safety_hours.Where(sh =&gt; sh.incident_id == i.incident_id).OrderBy(sh =&gt; sh.safety_hours_date))
              {
                  lostHours.Add(h);
              }
              i.LostHoursDetails = lostHours;
          }
      }
  
      public void SaveChanges()
      {
          // Assign new hours rows their safety incident.  Open to more automatic way...
          foreach (var si in _context.safety_incident)
          {
              foreach (var sh in si.LostHoursDetails.Where(h =&gt; h.incident_id == 0))
              {
                  sh.incident_id = si.incident_id;
              }
          }
          _context.SaveChanges();
      }
  </code></pre>
  
  <p>...</p>
  
  <p>Another point of complexity: before the _context.SaveChanges call, new incident rows (outer grid) will have an incident_id of 0, so how would any new hours rows (inner grid) know what to save for that?  Would something extra have to be done after the initial call, including a second call?  Thanks…</p>
  
  <p>PS Yes, I know my MVVM isn't pure, I just need something that works.</p>