I was curious how this would look so I put something together for you. Hopefully the comments are enough to push you in the right direction.
XAML:
<Window x:Class="multipleCheckBoxControlsDatagrid.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:multipleCheckBoxControlsDatagrid"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.Resources>
<!--DataTemplate for "listbox of checkboxes" column. Checks is a property on the ItemsSource of type DataGridRowData. Check is a property on the ItemsSource of type DataGridCellData -->
<DataTemplate x:Key="DataTemplate">
<ListBox ItemsSource="{Binding Checks}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<CheckBox IsChecked="{Binding Check}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</Grid.Resources>
<DataGrid x:Name="DataGrid1" AutoGenerateColumns="False" ItemsSource="{Binding DataGridDataCollection}">
<DataGrid.Columns>
<!--Custom column that contains a listbox of checkboxes-->
<DataGridTemplateColumn Header="Checks" CellTemplate="{StaticResource DataTemplate}" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
C#:
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
namespace multipleCheckBoxControlsDatagrid
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
// PropertyChanged event so the datagrid get updated when DataGridDataCollection changes
public event PropertyChangedEventHandler PropertyChanged;
// the datagrid binds to this collection
private ObservableCollection<DataGridRowData> _DataGridDataCollection;
public ObservableCollection<DataGridRowData> DataGridDataCollection
{
get => _DataGridDataCollection;
set
{
_DataGridDataCollection = value;
OnPropertyChanged();
}
}
public MainWindow()
{
DataGridDataCollection = new ObservableCollection<DataGridRowData>();
InitializeComponent();
this.DataContext = this;
addChecks();
}
// adds data to the DataGrid
private void addChecks()
{
DataGridDataCollection.Add(new DataGridRowData(new List<bool> { true, false, true }));
DataGridDataCollection.Add(new DataGridRowData(new List<bool> { false, true, false, false, true }));
DataGridDataCollection.Add(new DataGridRowData(new List<bool> { false, true, false, false, true, false, true }));
}
// PropertyChanged event so the datagrid get updated when DataGridDataCollection changes
protected void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
// this class represents one row of data in the data grid
// there is one column in this row named Checks
// the column is a list of DataGridCellData
// the listbox in each DataGrid cell binds to this
public class DataGridRowData
{
public List<DataGridCellData> Checks { get; set; }
public DataGridRowData(List<bool> checks)
{
Checks = new List<DataGridCellData>();
foreach(bool b in checks)
{
Checks.Add(new DataGridCellData(b));
}
}
}
// this class represents one unit of data in the above listbox
// so each cell in the DataGrid is bound to a ListBox and this class represents one line of data in that listbox
public class DataGridCellData
{
public bool Check { get; set; }
public DataGridCellData(bool check)
{
Check = check;
}
}
}