0

In the DataGrid control I would like to add a column in which each cell would contain a list of checkbox controls (for each cell there can be a different number of such checkboxes with different descriptions). I don't know how to define such a column with an undefined number of checkboxes in a cell.

Please help.

3
  • Welcome to SO. What did you try to do to solve your problem? Provide the code example, please. Commented Feb 19, 2021 at 13:12
  • 1
    I thought about it a bit and got the idea of ​​using a ListBox in a DataGridTemplate. Commented Feb 19, 2021 at 14:03
  • Would a treeview suit this better than a datagrid? Commented Feb 19, 2021 at 23:04

1 Answer 1

2

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;
        }
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.