title: WPF datagrid: Finding a control when adding a row
body: <p>So, basically I have a list of jobs that I'm keeping track of in a Datagrid.  In that datagrid, I have a button I want to be a "Cancel" button when the job is running, but otherwise be a "Retry" button.</p>
  
  <p>So, I've added the button to my grid:</p>
  
  <pre><code>&lt;DataGridTemplateColumn x:Name="JobActionColumn" Header=""&gt;
      &lt;DataGridTemplateColumn.CellTemplate&gt;
          &lt;DataTemplate&gt;
              &lt;Grid&gt;
                  &lt;Button Click="JobActionButton_Click" Content="Resend" Name="JobActionButton" Height="18" Width="45" Margin="0,0,0,0" /&gt;
              &lt;/Grid&gt; 
          &lt;/DataTemplate&gt;
      &lt;/DataGridTemplateColumn.CellTemplate&gt;
  &lt;/DataGridTemplateColumn&gt;
  </code></pre>
  
  <p>And in the code, I add my object in an ObservableCollection to add it to the grid:</p>
  
  <pre><code>    _jobs.Add(job);
      CollectionViewSource jobViewSource = this.FindViewSource("JobViewSource");
      jobViewSource.View.Refresh(); // Ensure that the new job appears at the top of the grid.
      JobDataGrid.SelectedItem = job;
  
      // Note: The Controller.Completed event handler disposes the controller object.
      Controller controller = new Controller(_historyContext);
      _controllers.Add(controller);
      controller.Completed += Controller_Completed;
      controller.Process(job);
  
      GetGridButton("JobActionButton", job).Content = "Cancel";
  </code></pre>
  
  <p>With GetGridButton being:</p>
  
  <pre><code>    private Button GetGridButton(string name, Job job)
      {            
          var selectedRow = (DataGridRow)JobDataGrid.ItemContainerGenerator.ContainerFromItem(job);
  
          return ExtensionMethods.FindVisualChildren&lt;Button&gt;(selectedRow).First(x =&gt; x.Name == name);            
      }
  </code></pre>
  
  <p>I've confirmed that <strong>GetGridButton</strong> works with rows that already exist.  The problem is that when you add a new row to the underlying dataset and call this, it can't find the <strong>DataGridRow</strong>.  I assume this is because it hasn't been created yet.  So, looking through events, it looked like that the <strong>LoadingRow</strong> event would be a good candidate:</p>
  
  <pre><code>    private void JobDataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
      {
          Job job = (Job)e.Row.Item;
  
          if (_controllers.FirstOrDefault(x =&gt; x.Job == job) != null)
          {
              var y = ExtensionMethods.FindVisualChildren&lt;Button&gt;(e.Row);
              Button button = ExtensionMethods.FindVisualChildren&lt;Button&gt;(e.Row).First(x =&gt; x.Name == "JobActionButton");
              button.Content = "Cancel";
          }
      }
  </code></pre>
  
  <p>So, now there is a <strong>DataGridRow</strong> object to pass into <strong>FindVisualChildren</strong>, but it still doesn't find any buttons.  So, is there any way for me to access this button on an added row?</p>