WPF DataGrid CheckBox Single Click Checking/Unchecking

WPF DataGrid has a very annoying behaviour of forcing users to click twice on a checkbox in order to check or uncheck it. There are a number of solutions proposing handling mouse preview events and switching a DataGrid into the edit mode manually. The problem with such solutions is that the require writing quite a lot of extra code that seems to be an overkill for such a minor, yet irritating problem. I propose a better option, to use a DataGridTemplateColumn instead of DataGridCheckBoxColumn.

Indeed, you can easily place a CheckBox inside a DataGridTemplateColumn, bind it to a corresponding property and it will be checkable/uncheckable with a single click.

XAML

<DataGrid Name="dgProducts" AutoGenerateColumns="False" CurrentCellChanged="dgProducts_CurrentCellChanged">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Name" Binding="{Binding Path=Name}"/>
        <DataGridTextColumn Header="Price" Binding="{Binding Path=Price}"/>
        <DataGridTemplateColumn Header="In Stock">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <CheckBox IsChecked="{Binding Path=IsInStock}">
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

Code-behind

public partial class MainWindow : Window
{
  ProductsEntities db = new ProductsEntities();

  public MainWindow()
  {
    InitializeComponent();

    var products = from p in this.db.Products
                    select p;

    dgProducts.ItemsSource = products;
  }

  private void dgProducts_CurrentCellChanged(object sender, EventArgs e)
  {
    this.db.SaveChanges();
  }
}

However, this piece of code still has a problem, in order to send update to a database user must edit any other column after modifying a checkbox. But it’s pretty easy to overcome this issue, first of all, we have to put UpdateSourceTrigger="PropertyChanged" to the binding section of a checkbox and then handle its Click event.

XAML:

<CheckBox IsChecked="{Binding Path=IsInStock, UpdateSourceTrigger=PropertyChanged}" Click="CheckBox_Click"/>

Code-Behind:

private void CheckBox_Click(object sender, RoutedEventArgs e)
{
  MessageBox.Show("click");
  this.db.SaveChanges();
}
Mike Borozdin (Twitter)
13 June 2011

The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way. My personal thoughts tend to change, hence the articles in this blog might not provide an accurate reflection of my present standpoint.

© Mike Borozdin