Over the period of time lot of asks and solutions were made for selectall selector for DataGrid. However, I failed to see a solution which is completely built on XAML. When my friend approached me, I thought that I will write my own.
The idea is to have a template column with a separate definition for the header and the rows. To avoid using code behind for the solution, I decided to use two data templates for the header and the row items.
<DataGrid x:Name="TestGrid" > <DataGrid.Resources > <DataTemplate x:Key="HeaderCheckbox" > <CheckBox Name="SelectAll" IsChecked="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}, Path=Tag, Mode=TwoWay}" / > </DataTemplate > <DataTemplate x:Key="ItemCheckbox" > <CheckBox IsChecked="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}, Path=Tag, Mode=OneWay}" / > </DataTemplate > </DataGrid.Resources > <DataGrid.Columns > <DataGridTemplateColumn HeaderTemplate="{StaticResource HeaderCheckbox}" CellTemplate="{StaticResource ItemCheckbox}" / > <DataGridTextColumn Binding="{Binding FirstName}" / > </DataGrid.Columns > </DataGrid >
In the above snippet we have got a template “HeaderCheckbox” which is defined as a header template and two way bound to the “Tag” property of the grid. We have another template “ItemCheckbox” which is for all the rows again bound to the same “Tag” property but as a read-only. We are using “Tag” as an intermediate placeholder as we don’t have a direct solution to refer a datatemplate from another. Also, we have defaulted the “Tag” to “False” which will make all the checkboxes to be in unselected mode during the initial binding.
Lets now discuss the operation of the solution
- When the user selects / unselects the checkbox in the header, the corresponding value is set to the “Tag” property of the grid control.
- The “Tag” property whenever changed, propagates the value to all the item checkboxes as they are one-way (read-only) bound to the property.
- Changing the checkboxes in the items will not affect the header checkbox as they are only bound to read from the tag and not to write back.