How to select all CheckBox columns using DataGrid Header CheckBox in WPF DataGrid

I have a DataGrid with one CheckBoxColumn. In the header of this CheckBoxColumn, I added a CheckBox to select all the CheckBoxes of this Datagrid row.

How can i achieve this?

My XAML code for WPF dataGrid:

<DataGrid AutoGenerateColumns="False" CanUserAddRows="False" Grid.RowSpan="2" Height="130" HorizontalAlignment="Left" IsReadOnly="False" Margin="189,340,0,0" Name="dgCandidate" TabIndex="7" VerticalAlignment="Top" Width="466" Grid.Row="1" > <DataGrid.Columns> <DataGridTextColumn x:Name="colCandidateID" Binding="{Binding CandidateID}" Header="SlNo" MinWidth="20" IsReadOnly="True" /> <DataGridTextColumn x:Name="colRegistraion" Binding="{Binding RegisterNo}" Header="Reg. No." IsReadOnly="True" /> <DataGridTextColumn x:Name="colCandidate" Binding="{Binding CandidateName}" Header="Name" MinWidth="250" IsReadOnly="True" /> <DataGridTemplateColumn> <DataGridTemplateColumn.Header> <CheckBox Name="chkSelectAll" Checked="chkSelectAll_Checked" Unchecked="chkSelectAll_Unchecked"></CheckBox> </DataGridTemplateColumn.Header> <DataGridTemplateColumn.CellTemplate > <DataTemplate > <CheckBox x:Name="colchkSelect1" Checked="colchkSelect1_Checked" Unchecked="colchkSelect1_Unchecked" ></CheckBox> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid> 
+6
source share
4 answers

Convert the Candidate class to something like this:

 public class Candidate : DependencyObject { //CandidateID Dependency Property public int CandidateID { get { return (int)GetValue(CandidateIDProperty); } set { SetValue(CandidateIDProperty, value); } } public static readonly DependencyProperty CandidateIDProperty = DependencyProperty.Register("CandidateID", typeof(int), typeof(Candidate), new UIPropertyMetadata(0)); //RegisterNo Dependency Property public int RegisterNo { get { return (int)GetValue(RegisterNoProperty); } set { SetValue(RegisterNoProperty, value); } } public static readonly DependencyProperty RegisterNoProperty = DependencyProperty.Register("RegisterNo", typeof(int), typeof(Candidate), new UIPropertyMetadata(0)); //CandidateName Dependency Property public string CandidateName { get { return (string)GetValue(CandidateNameProperty); } set { SetValue(CandidateNameProperty, value); } } public static readonly DependencyProperty CandidateNameProperty = DependencyProperty.Register("CandidateName", typeof(string), typeof(Candidate), new UIPropertyMetadata("")); //BooleanFlag Dependency Property public bool BooleanFlag { get { return (bool)GetValue(BooleanFlagProperty); } set { SetValue(BooleanFlagProperty, value); } } public static readonly DependencyProperty BooleanFlagProperty = DependencyProperty.Register("BooleanFlag", typeof(bool), typeof(Candidate), new UIPropertyMetadata(false)); } 

in MainWindow.xaml:

 <DataGrid ItemsSource="{Binding CandidateList}"> <DataGrid.Columns> <DataGridTextColumn Header="Id" Binding="{Binding CandidateID}"/> <DataGridTextColumn Header="RegNr" Binding="{Binding RegisterNo}"/> <DataGridTextColumn Header="Name" Binding="{Binding CandidateName}"/> <DataGridTemplateColumn> <DataGridTemplateColumn.Header> <CheckBox Checked="CheckBox_Checked" Unchecked="CheckBox_Checked"></CheckBox> </DataGridTemplateColumn.Header> <DataGridTemplateColumn.CellTemplate > <DataTemplate> <CheckBox IsChecked="{Binding BooleanFlag}"/> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid> 

in MainWindow.xaml.cs:

  public MainWindow() { DataContext = this; CandidateList.Add(new Candidate() { CandidateID = 1, CandidateName = "Jack", RegisterNo = 123, BooleanFlag = true }); CandidateList.Add(new Candidate() { CandidateID = 2, CandidateName = "Jim", RegisterNo = 234, BooleanFlag = false }); InitializeComponent(); } //List Observable Collection private ObservableCollection<Candidate> _candidateList = new ObservableCollection<Candidate>(); public ObservableCollection<Candidate> CandidateList { get { return _candidateList; } } private void CheckBox_Checked(object sender, RoutedEventArgs e) { foreach (var item in CandidateList) { item.BooleanFlag = true; } } private void UnheckBox_Checked(object sender, RoutedEventArgs e) { foreach (var item in CandidateList) { item.BooleanFlag = false; } } 
+5
source

Strictly speaking, the model does not need to know about the presentation, and therefore the solution proposed by blindmeis, where changing the model updates each row in the datagrid, violates the MVVM / Presentation Design pattern. Remember that in MVVM, the dependency stream is View β†’ ViewModel β†’ Model, so if you reference the controls in your view model (or control the code), then you have violated the template effectively, and you will probably run into problems later on track.

+3
source

I added a CheckBox to select all the CheckBox in the Datagrid row

if you mean the β€œSelect All” checkbox in the datagrid column then I would say: just update the itemssource collection with check / unchecked.

 public bool SelectAll { get{return this._selectAll;} set { this._selectAll = value; this.MyItemsSourceCollection.ForEach(x=>x.MyRowCheckProperty=value); this.OnPropertyChanged("SelectAll"); } } 

Xaml

  <DataGridTemplateColumn> <DataGridTemplateColumn.Header> <CheckBox isChecked="{Binding SelectAll}"></CheckBox> </DataGridTemplateColumn.Header> <DataGridTemplateColumn.CellTemplate > <DataTemplate > <CheckBox IsChecked="{Binding MyRowCheckProperty}"></CheckBox> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> 

i dunno if xaml bindings are correct, but I hope you can see my intention

+2
source

Turns out it's a lot harder than you can hope for.

The first problem is that you cannot just bind the view model to the column heading because it does not have the view model as its data context, so you need a connecting proxy to properly direct the binding to the view model.

 public class BindingProxy : Freezable { public static readonly DependencyProperty DataProperty = DependencyProperty.Register( "Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null)); public object Data { get { return this.GetValue(DataProperty); } set { this.SetValue(DataProperty, value); } } protected override Freezable CreateInstanceCore() { return new BindingProxy(); } } 

Now create a binding proxy in the data grid resources:

 <DataGrid.Resources> <aon:BindingProxy x:Key="DataContextProxy" Data="{Binding}" /> </DataGrid.Resources> 

Then the column should be defined as:

 <DataGridTemplateColumn> <DataGridTemplateColumn.HeaderTemplate> <DataTemplate> <CheckBox Command="{Binding Data.SelectAllCommand, Source={StaticResource DataContextProxy}}" IsChecked="{Binding Data.AreAllSelected, Mode=OneWay, Source={StaticResource DataContextProxy}, UpdateSourceTrigger=PropertyChanged}" IsThreeState="True" /> </DataTemplate> </DataGridTemplateColumn.HeaderTemplate> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <CheckBox IsChecked="{Binding Path=IsSelected, UpdateSourceTrigger=PropertyChanged}" /> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> 

Note that you need to bind both the IsChecked dependency property and the Command property, and the IsChecked binding IsChecked be OneWay . The IsChecked binding receives a flag to display the current state of the elements, and the Command binding selects the mass. You need both.

Now in the view model:

 public bool? AreAllSelected { get { return this.Items.All(candidate => candidate.IsSelected) ? true : this.Items.All(candidate => !candidate.IsSelected) ? (bool?)false : null; } set { if (value != null) { foreach (var item in this.Items) { item.IsSelected = value.Value; } } this.RaisePropertyChanged(); } } 

And the SelectAllCommand property is an implementation of ICommand , where the Execute method:

 public void Execute(object parameter) { var allSelected = this.AreAllSelected; switch (allSelected) { case true: this.AreAllSelected = false; break; case false: case null: this.AreAllSelected = true; break; } } 

Finally, your line item position model (i.e., things in Items ) should raise the PropertyChanged in the main view model every time the IsSelected value IsSelected . How you do this is largely up to you.

0
source

All Articles