WPF DataGrid – New Item Template Sample

This sample shows how to create a template for the NewItemPlaceholder to indicate that you can add a new item. This is what it will look like:

newitemtemplate

First I will need to create a new template specifically for the NewItemPlaceholder row. I’ve followed the general outline of the original DataGridRow control template but I’ve only included the pieces I needed and I’ve also added an element for the “Click here to add new item.” text. My template looks something like this:           

<ControlTemplate x:Key="NewRow_ControlTemplate" TargetType="{x:Type dg:DataGridRow}">

  <Border x:Name="DGR_Border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="True">

      <dg:SelectiveScrollingGrid>

        …

        <TextBlock Text="Click here to add a new item." Grid.Column="1"/>

        …

      </dg:SelectiveScrollingGrid>

</ControlTemplate>

 

Then I’m going to need to attach to several events. In particular, I need to hook up to the DataGrid.LoadingRow, DataGrid.UnloadingRow, DataGrid.RowEditEnding, and DataGridRow.MouseLeftButtonDown events.

I attach to the LoadingRow and UnloadingRow events so I can set either the default or new item control template when the row is created. These event handlers will look like this:

private void DataGrid_Standard_LoadingRow(object sender, DataGridRowEventArgs e)

{

  if (_defaultRowControlTemplate == null)

  {

    _defaultRowControlTemplate = e.Row.Template;

  }

  if (e.Row.Item == CollectionView.NewItemPlaceholder)

  {

      e.Row.Template = _newRowControlTemplate;

      e.Row.UpdateLayout();

  }

}

private void DataGrid_Standard_UnloadingRow(object sender, DataGridRowEventArgs e)

{

  if (e.Row.Item == CollectionView.NewItemPlaceholder && e.Row.Template != _defaultRowControlTemplate)

  {

      e.Row.Template = _defaultRowControlTemplate;

      e.Row.UpdateLayout();

  }

}

 

I attach to the DataGridRow.MouseLeftButtonDown event so that I can change the template of the NewItemPlaceholder on the first click. For this sample, when first clicking the row of the NewItemPlaceholder it immediate enters edit mode. Here is the handler:

private void Row_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)

{

  DataGridRow row = sender as DataGridRow;

  if (row.Item == CollectionView.NewItemPlaceholder && row.Template == _newRowControlTemplate)

  {

      // for a new row update the template and open for edit

      row.Template = _defaultRowControlTemplate;

      row.UpdateLayout();

      DataGrid_Standard.CurrentItem = row.Item;

      DataGridCell cell = Helper.GetCell(DataGrid_Standard, DataGrid_Standard.Items.IndexOf(row.Item), 0);

cell.Focus();

      DataGrid_Standard.BeginEdit();

  }

}

 

The last event is necessary so that the template is updated back to the new item template after a row is either committed or cancelled. It is a little tricky because what I really want is to perform my operation when the row is already committed or cancelled but the only event available, RowEditEnding, fires while the row is committing or being cancelled. What I can do is use the Dispatcher to make my operation take place after the RowEditEnding event. My handler looks like this:          

private void DataGrid_Standard_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e)

{

  IEditableCollectionView iecv = CollectionViewSource.GetDefaultView((sender as DataGrid).ItemsSource) as IEditableCollectionView;

  if (iecv.IsAddingNew)

  {

      // need to wait till after the operation as the NewItemPlaceHolder is added after

      Dispatcher.Invoke(new DispatcherOperationCallback(ResetNewItemTemplate), DispatcherPriority.ApplicationIdle, DataGrid_Standard);

  }

}

private object ResetNewItemTemplate(object arg)

{

  DataGridRow row = Helper.GetRow(DataGrid_Standard, DataGrid_Standard.Items.Count - 1);

  if (row.Template != _newRowControlTemplate)

  {

      row.Template = _newRowControlTemplate;

      row.UpdateLayout();

   }

  return null;

}

 

So when I cancel or commit the edit on the new item, the new item template will be added back to the last row.

You can download the full sample here.

DataGrid_V1_NewItemTemplate_Sample.zip