TL; DR; This is what you need, the code below:

ViewModel. CheckBox , :
CheckBox , / , CheckBox - CheckBox , . : . , - CheckBox CheckBox .
:
ViewModel , , IsChecked.
public class Entry : INotifyPropertyChanged
{
private bool _isChecked;
public bool IsChecked
{
get => _isChecked;
set
{
if (value == _isChecked) return;
_isChecked = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
ViewModel . , item IsChecked, , /strong CheckBox (, , ).
public class ViewModel : INotifyPropertyChanged
{
public List<Entry> Entries
{
get => _entries;
set
{
if (Equals(value, _entries)) return;
_entries = value;
OnPropertyChanged();
}
}
public ViewModel()
{
Entries = new List<Entry>
{
new Entry(),
new Entry(),
new Entry(),
new Entry()
};
foreach (Entry entry in Entries)
{
entry.PropertyChanged += EntryOnPropertyChanged;
}
}
private void EntryOnPropertyChanged(object sender, PropertyChangedEventArgs args)
{
if(args.PropertyName == nameof(Entry.IsChecked))
RecheckAllSelected();
}
private void AllSelectedChanged()
{
if (_allSelectedChanging) return;
try
{
_allSelectedChanging = true;
if (AllSelected == true)
{
foreach (Entry kommune in Entries)
kommune.IsChecked = true;
}
else if (AllSelected == false)
{
foreach (Entry kommune in Entries)
kommune.IsChecked = false;
}
}
finally
{
_allSelectedChanging = false;
}
}
private void RecheckAllSelected()
{
if (_allSelectedChanging) return;
try
{
_allSelectedChanging = true;
if (Entries.All(e => e.IsChecked))
AllSelected = true;
else if (Entries.All(e => !e.IsChecked))
AllSelected = false;
else
AllSelected = null;
}
finally
{
_allSelectedChanging = false;
}
}
public bool? AllSelected
{
get => _allSelected;
set
{
if (value == _allSelected) return;
_allSelected = value;
AllSelectedChanged();
OnPropertyChanged();
}
}
private bool _allSelectedChanging;
private List<Entry> _entries;
private bool? _allSelected;
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
- XAML:
<DataGrid ItemsSource="{Binding Entries}" AutoGenerateColumns="False" IsReadOnly="False" CanUserAddRows="False">
<DataGrid.Columns>
<DataGridCheckBoxColumn Binding="{Binding IsChecked, UpdateSourceTrigger=PropertyChanged}">
<DataGridCheckBoxColumn.HeaderTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:MainWindow}, Path=ViewModel.AllSelected}">Select All</CheckBox>
</DataTemplate>
</DataGridCheckBoxColumn.HeaderTemplate>
</DataGridCheckBoxColumn>
</DataGrid.Columns>
</DataGrid>