Showing posts with label DataGrid. Show all posts
Showing posts with label DataGrid. Show all posts

Tuesday, June 22, 2010

How to center a check box column in the WPF DataGrid

A common problem with the DataGridCheckBoxColumn of the WPF DataGrid is that the CheckBox is not centered in the cell which is especially ugly in rows that are higher than the CheckBox itself.
Due to the nature of how a column in the DataGrid is generated it isn't very easy to use a simple style or ones own template column.

But there is a much shorter and better way, we can simply extend the DataGridCheckBoxColumn to provide our own, centered, CheckBox.

public class CenteredCheckBoxColumn 
           : DataGridCheckBoxColumn 
{
  protected override FrameworkElement 
    GenerateEditingElement(
      DataGridCell cell, object dataItem) 
  {
    var checkBox = 
      base.GenerateEditingElement(cell, dataItem);
    checkBox.HorizontalAlignment = 
      HorizontalAlignment.Center;
    checkBox.VerticalAlignment = 
      VerticalAlignment.Center;
    return checkBox;
  }

  protected override FrameworkElement GenerateElement(
      DataGridCell cell, object dataItem) 
  {
    var checkBox = 
      base.GenerateElement(cell, dataItem);
    checkBox.HorizontalAlignment = 
      HorizontalAlignment.Center;
    checkBox.VerticalAlignment = 
      VerticalAlignment.Center;
    return checkBox;
  }
}

We can now use our CenteredCheckBoxColumn in the same way we use the standard columns.

Submit this story to DotNetKicks

Thursday, May 20, 2010

Committing bound cell changes immediately in WPF Datagrid

The WPF DataGrids default mode of operation is committing all changes on a per-row edit instead of a per-cell edit. In this post we will see how to change that behavior to do a per-cell commit regardless of the bound object's capabilities.

But first a little bit about the workings of the DataGrid.
When binding data in a WPF DataGrid it holds all changes to the data in an intermediary object. If the user edits a cell the changes will be done only in this intermediary object, the exception being if the bound object does implement IEditableObject in which case the DataGrid uses the object's edit capabilities instead.
But if we do not have an IEditableObject to bind to all changes made inside the row will only be committed to the bound object once the row edit ends. If we still need to commit on a cell by cell basis we need to attach a handler to the CellEditEnding event of the grid and use the following code in the handler.

private bool isManualEditCommit;
private void HandleMainDataGridCellEditEnding(
  object sender, DataGridCellEditEndingEventArgs e) 
{
 if (!isManualEditCommit) 
 {
  isManualEditCommit = true;
  DataGrid grid = (DataGrid)sender;
  grid.CommitEdit(DataGridEditingUnit.Row, true);
  isManualEditCommit = false;
 }
}

This will update the bound object whenever a cell edit is ending, i.e. whenever the cell looses focus.

Submit this story to DotNetKicks