0

I am adding dynamically checkbox columns to WPF datagrid based on user interactions (button clicks, checkboxes etc). I need also to add an Select all checkbox to column header programmatically. Any ideas how to do it?

 DataGridCheckBoxColumn  checkBoxColumn=new DataGridCheckBoxColumn();
 checkBoxColumn.Header = "Title";
 checkBoxColumn.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
 checkBoxColumn.Binding = new Binding(e.PropertyName);
 checkBoxColumn.IsThreeState = true;

I would do it through XAML it should look something like this

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

1 Answer 1

1

Maybe I did not understand your question, but do you mean something like this?

Binding binding = new Binding("SelectAll");
binding.Mode = BindingMode.TwoWay;

CheckBox headerCheckBox = new CheckBox();
headerCheckBox.Content = "Title";
headerCheckBox.SetBinding(CheckBox.IsCheckedProperty, binding);

DataGridCheckBoxColumn checkBoxColumn = new DataGridCheckBoxColumn();
checkBoxColumn.Header = headerCheckBox;
checkBoxColumn.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
checkBoxColumn.Binding = new Binding(e.PropertyName);
checkBoxColumn.IsThreeState = true;

I hope so.

EDIT

It is strange the behavoiur that you describe in your comment. However this is the complete project (I used .NET 4.0).

XAML:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="600">
    <StackPanel>
        <DataGrid Name="dataGrid" AutoGenerateColumns="False" ItemsSource="{Binding Mode=OneWay, Path=Parties}">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Name" Binding="{Binding Name}" Width="*" />
                <DataGridTextColumn Header="Surname" Binding="{Binding Surname}" Width="*" />
            </DataGrid.Columns>
        </DataGrid>
    </StackPanel>
</Window>

Model:

namespace WpfApplication1
{
    public class Party : INotifyPropertyChanged
    {
        private bool isSelected;
        private string name;
        private string surname;

        public event PropertyChangedEventHandler PropertyChanged;

        public bool IsSelected
        {
            get
            {
                return isSelected;
            }
            set
            {
                if (isSelected != value)
                {
                    isSelected = value;
                    OnPropertyChanged("IsSelected");
                }
            }
        }

        public string Name
        {
            get
            {
                return name;
            }
            set
            {
                if (name != value)
                {
                    name = value;
                    OnPropertyChanged("Name");
                }
            }
        }

        public string Surname
        {
            get
            {
                return surname;
            }
            set
            {
                if (surname != value)
                {
                    surname = value;
                    OnPropertyChanged("Surname");
                }
            }
        }

        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

ViewModel (you can improve the INotifyPropertyChanged implementation, by creating a base class):

namespace WpfApplication1
{
    public class ViewModel : INotifyPropertyChanged
    {
        private bool selectAll;
        private readonly ObservableCollection<Party> parties = new ObservableCollection<Party>();

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public ObservableCollection<Party> Parties
        {
            get
            {
                return parties;
            }
        }

        public bool SelectAll
        {
            get
            {
                return selectAll;
            }
            set
            {
                if (selectAll != value)
                {
                    selectAll = value;
                    OnPropertyChanged("SelectAll");
                    SelectAllImpl(selectAll);
                }
            }
        }

        private void SelectAllImpl(bool isSelected)
        {
            foreach (Party party in parties)
            {
                party.IsSelected = isSelected;
            }
        }
    }
}

And then XAML code behind:

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            ViewModel viewModel = new ViewModel();
            viewModel.Parties.Add(new Party() { Name = "Joe", Surname = "Redgate" });
            viewModel.Parties.Add(new Party() { Name = "Mike", Surname = "Blunt" });
            viewModel.Parties.Add(new Party() { Name = "Gina", Surname = "Barber" });

            DataContext = viewModel;

            Binding binding = new Binding("DataContext.SelectAll");
            binding.Mode = BindingMode.TwoWay;
            binding.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor);
            binding.RelativeSource.AncestorType = GetType();

            CheckBox headerCheckBox = new CheckBox();
            headerCheckBox.Content = "Is Selected";
            headerCheckBox.SetBinding(CheckBox.IsCheckedProperty, binding);

            DataGridCheckBoxColumn checkBoxColumn = new DataGridCheckBoxColumn();
            checkBoxColumn.Header = headerCheckBox;
            checkBoxColumn.Binding = new Binding("IsSelected");


            dataGrid.Columns.Insert(0, checkBoxColumn);
        }
    }
}

And this is the result: Screenshot

Sign up to request clarification or add additional context in comments.

7 Comments

Something like this ... but your sample is not working unfortunately. CheckBox is not resolved in Header
Do you mean the checkbox does not appear in the column header? I can post more code if you need.
Correct ... instead of checkbox a name of the control is shown... I would appreciate if you post somehing workable:) thx
Something that everybody seems to forget is that your header checkbox should be unticked/semi-ticked as soon as a row in the grid becomes unchecked. Hence, this image is invalid :)
You are right @mstaessen; indeed it is not so difficult to update the header checkbox. The ViewModel can handle this.
|

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.