Unplanned
Last Updated: 14 Apr 2020 15:26 by ADMIN
Akarsh
Created on: 14 Apr 2020 14:58
Category: UI for WinForms
Type: Bug Report
0
RadGridView: header check box doesn't work properly when the ShouldCheckDataRows property is set to false

Please refer to the attached sample project and gif file. The ShouldCheckDataRows property of the column is disabled. Hence, the developer will manage the toggle state of the data cells.

There are two problems here:

1. In the HeaderCellToggleStateChanged event we toggle all data rows in correspondence with the header checkbox. Once a data cell value is changed, we set the GridViewCheckBoxColumn.Checked property to Off. However, it is not respected and the header checkbox still remains toggle.

2. Once you scroll the columns horizontally, the header checkbox synchronizes with the value of the GridViewCheckBoxColumn.Checked property. However, all of a sudden the HeaderCellToggleStateChanged event is toggled again even though we didn't clicked the checkbox in the header at all. This will make all data cells unchecked due to the code in the HeaderCellToggleStateChanged event.

1 comment
ADMIN
Dess | Tech Support Engineer, Principal
Posted on: 14 Apr 2020 15:26

Hello, Akarsh,

Thank you for reporting this.

The possible solution that I can suggest is to create a custom checkbox column that manages the check boxes in the way you want. I have attached my sample project for your reference which result is illustrated in the attached gif file:

 

 public partial class RadForm1 : Telerik.WinControls.UI.RadForm
    {
        GridViewCheckBoxColumn checkColumn = new GridViewCheckBoxColumn("Select"); 

        public RadForm1()
        {
            InitializeComponent();

            this.radGridView1.Relations.AddSelfReference(this.radGridView1.MasterTemplate, "id", "pid");
            this.radGridView1.DataSource = GetSampleData();

            checkColumn.EditMode = EditMode.OnValueChange;
            checkColumn.EnableHeaderCheckBox = true;
            checkColumn.ShouldCheckDataRows = false;
            this.radGridView1.HeaderCellToggleStateChanged += grdData_HeaderCellToggleStateChanged;
            this.radGridView1.CellValueChanged += radGridView1_CellValueChanged;
            this.radGridView1.Columns.Insert(0, checkColumn);

            CustomGridViewDataColumn customCol = new CustomGridViewDataColumn() { Name = "CustomCol", FieldName = "CustomCol" };
            this.radGridView1.Columns.Add(customCol);
        }

        private void radGridView1_CellValueChanged(object sender, GridViewCellEventArgs e)
        {
            if (e.Column.Name == "Select" && e.Row is GridViewDataRowInfo)
            { 
                checkColumn.Checked = ToggleState.Off;
            }
            if (e.Column.Name == "CustomCol" && e.Row is GridViewDataRowInfo && e.Column.Tag == null)
            {
                ((CustomGridViewDataColumn)e.Column).Checked = false;
            }
            this.radGridView1.MasterView.TableHeaderRow.InvalidateRow();
        }

        private void grdData_HeaderCellToggleStateChanged(object sender, GridViewHeaderCellEventArgs e)
        {
            this.radGridView1.HeaderCellToggleStateChanged -= grdData_HeaderCellToggleStateChanged;
            this.radGridView1.CellValueChanged -= radGridView1_CellValueChanged;
            
            this.radGridView1.TableElement.BeginUpdate();
            foreach (GridViewDataRowInfo row in this.radGridView1.Rows)
            {
                row.Cells["Select"].Value = e.State == ToggleState.On ? true : false; 
            }
            this.radGridView1.TableElement.EndUpdate();

            this.radGridView1.CellValueChanged += radGridView1_CellValueChanged;
            this.radGridView1.HeaderCellToggleStateChanged += grdData_HeaderCellToggleStateChanged; 
        }

        private DataTable GetSampleData()
        {
            DataTable dt = new DataTable();

            DataColumn dc = new DataColumn();
            dc.ColumnName = "id";
            dc.DataType = typeof(int);
            dt.Columns.Add(dc);

            DataColumn dc1 = new DataColumn();
            dc1.ColumnName = "name";
            dc1.DataType = typeof(string);
            dt.Columns.Add(dc1);

            DataColumn dc2 = new DataColumn();
            dc2.ColumnName = "pid";
            dc2.DataType = typeof(int);
            dt.Columns.Add(dc2);

            DataRow dr = dt.NewRow();
            dr[0] = 0;
            dr[1] = "My Computer";
            dr[2] = DBNull.Value;
            dt.Rows.Add(dr);

            dr = dt.NewRow();
            dr[0] = 7;
            dr[1] = @"Downloads\";
            dr[2] = DBNull.Value;
            dt.Rows.Add(dr);

            dr = dt.NewRow();
            dr[0] = 1;
            dr[1] = @"C:\";
            dr[2] = 0;
            dt.Rows.Add(dr);

            dr = dt.NewRow();
            dr[0] = 2;
            dr[1] = @"D:\";
            dr[2] = 0;
            dt.Rows.Add(dr);

            dr = dt.NewRow();
            dr[0] = 3;
            dr[1] = "Program Files";
            dr[2] = 1;
            dt.Rows.Add(dr);

            dr = dt.NewRow();
            dr[0] = 4;
            dr[1] = "Microsoft";
            dr[2] = 3;
            dt.Rows.Add(dr);

            dr = dt.NewRow();
            dr[0] = 5;
            dr[1] = "Telerik";
            dr[2] = 3;
            dt.Rows.Add(dr);

            dr = dt.NewRow();
            dr[0] = 6;
            dr[1] = "WINDOWS";
            dr[2] = 1;
            dt.Rows.Add(dr);

            return dt;
        }

        public class CustomGridViewDataColumn : GridViewDataColumn
        {
            public bool Checked { get; set; }

            public override Type GetCellType(GridViewRowInfo row)
            {
                if (row is GridViewTableHeaderRowInfo)
                {
                    return typeof(CustomGridHeaderCellElement);
                }
                else if (row is GridViewDataRowInfo || row is GridViewNewRowInfo)
                {
                    return typeof(CustomDataCell);
                }
                return base.GetCellType(row); 
            }
        }

        public class CustomGridHeaderCellElement : GridHeaderCellElement
        {
            protected override Type ThemeEffectiveType
            {
                get
                {
                    return typeof(GridHeaderCellElement);
                }
            }

            public CustomGridHeaderCellElement(GridViewColumn column, GridRowElement row) : base(column, row)
            {
            }

            RadCheckBoxElement checkBox;

            protected override void CreateChildElements()
            {
                base.CreateChildElements();
                checkBox = new RadCheckBoxElement();
                checkBox.ToggleStateChanged += checkbox_ToggleStateChanged;
                this.Children.Add(checkBox);
            }

            private void checkbox_ToggleStateChanged(object sender, StateChangedEventArgs args)
            {
                ((CustomGridViewDataColumn)this.ColumnInfo).Checked = args.ToggleState == ToggleState.On ? true : false;
                this.ColumnInfo.Tag = "Suspend";
                
                foreach (GridViewRowInfo row in this.GridControl.Rows)
                {
                    row.Cells[this.ColumnInfo.Name].Value = args.ToggleState == ToggleState.On ? true : false;
                }
                
                this.ColumnInfo.Tag = null;
            }

            public override void SetContent()
            {
                base.SetContent();

                checkBox.ToggleStateChanged -= checkbox_ToggleStateChanged;
                checkBox.Checked = ((CustomGridViewDataColumn)this.ColumnInfo).Checked;
                checkBox.ToggleStateChanged += checkbox_ToggleStateChanged;
            }
        }

        public class CustomDataCell : GridDataCellElement
        { 
            public CustomDataCell(GridViewColumn column, GridRowElement row) : base(column, row)
            {
            }

            protected override Type ThemeEffectiveType
            {
                get
                {
                    return typeof(GridDataCellElement);
                }
            }

            RadCheckBoxElement checkBox;

            protected override void CreateChildElements()
            {
                base.CreateChildElements();
                checkBox = new RadCheckBoxElement();
                checkBox.ToggleStateChanged += checkbox_ToggleStateChanged;
                this.Children.Add(checkBox);
            }

            private void checkbox_ToggleStateChanged(object sender, StateChangedEventArgs args)
            {
                this.RowInfo.Cells[this.ColumnInfo.Name].Value = args.ToggleState == ToggleState.On ? true : false;
            }

            public override void SetContent()
            {
                base.SetContent();
                this.DrawText = false;
                if (this.RowInfo == null || this.RowInfo.Cells[this.ColumnInfo.Name].Value == null)
                {
                    return;
                }
                checkBox.ToggleStateChanged -= checkbox_ToggleStateChanged;
                checkBox.Checked = GetBoolValue(this.RowInfo.Cells[this.ColumnInfo.Name].Value);
                checkBox.ToggleStateChanged += checkbox_ToggleStateChanged;
            }

            private bool GetBoolValue(object val)
            {
                if (val + "" == "True")
                {
                    return true;
                }
                if (val is bool)
                {
                    return (bool)val;
                }

                return false;
            }
        }
    }

Note that this is just a sample approach and it may not cover all possible cases. Feel free to modify and extend it in a way which suits your requirements best.

I hope this information helps.

Regards,
Dess | Tech Support Engineer, Sr.
Progress Telerik

Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
Our thoughts here at Progress are with those affected by the outbreak.