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();
}
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