New to Telerik UI for WinForms? Download free 30-day trial

“Check all” functionality in group rows

Product Version Product Author Last modified
2017.3.912 RadGridView for WinForms Desislava Yordanova October 02, 2017

Problem

By default, the group rows in RadGridView display the group value and the added aggregates to the GroupDescriptor. A common scenario is to check/uncheck all rows from a certain group by a check box placed in the group header.
checkAll

Solution

We will create a derivative of GridGroupContentCellElement and insert a RadCheckBoxElement in the cell’s children. For the correct layout of the group row element, the text will be visualized in a LightVisualElement next to the check box. Both of the elements will be hosted in StackLayoutElement. When the check box is toggled, all rows that belong to the group should be updated.

public class CustomGridGroupContentCellElement : GridGroupContentCellElement
{
    RadCheckBoxElement checkBoxElement = new RadCheckBoxElement();
    LightVisualElement textElement = new LightVisualElement();
    StackLayoutElement stack = new StackLayoutElement();

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

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

    protected override void CreateChildElements()
    {
        base.CreateChildElements();
        stack = new StackLayoutElement();
        stack.Orientation = Orientation.Horizontal;
        stack.StretchHorizontally = true;

        checkBoxElement.StretchHorizontally = false;
        checkBoxElement.CheckStateChanged += checkBoxElement_CheckStateChanged;
        textElement.TextAlignment = ContentAlignment.MiddleLeft;
        this.Children.Add(stack);
        stack.Children.Add(checkBoxElement);
        stack.Children.Add(textElement);
    }

    private void checkBoxElement_CheckStateChanged(object sender, EventArgs e)
    {
        //update child rows
        GridViewGroupRowInfo group = this.RowInfo as GridViewGroupRowInfo;
        group.Tag = checkBoxElement.Checked;
        this.GridViewElement.GridControl.BeginUpdate();
        int scrollValue = this.GridControl.TableElement.VScrollBar.Value;
        foreach (GridViewRowInfo row in this.RowInfo.ChildRows)
        {
            GridViewGroupRowInfo groupRow = row as GridViewGroupRowInfo;
            if (groupRow != null)
            {
                Toggle(groupRow, checkBoxElement.Checked);
            }

            row.Cells["Discontinued"].Value = checkBoxElement.Checked;
        }
        this.GridViewElement.GridControl.EndUpdate();
        this.GridViewElement.GridControl.TableElement.VScrollBar.Value = scrollValue;
    }

    private void Toggle(GridViewGroupRowInfo groupRow, bool state)
    {
        groupRow.Tag = state;
        foreach (GridViewRowInfo row in groupRow.ChildRows)
        {
            GridViewGroupRowInfo g = row as GridViewGroupRowInfo;
            if (g != null)
            {
                Toggle(g, state);
            }

            row.Cells["Discontinued"].Value = state;
        }
    }

    public override void SetContent()
    {
        base.SetContent();
        this.DrawText = false;
        textElement.Text = ((GridViewGroupRowInfo)this.RowInfo).HeaderText;
        checkBoxElement.CheckStateChanged -= checkBoxElement_CheckStateChanged;
        if (this.RowInfo.Tag != null)
        {
            checkBoxElement.Checked = (bool)this.RowInfo.Tag;
        }
        else
        {
            checkBoxElement.Checked = false;
        }
        checkBoxElement.CheckStateChanged += checkBoxElement_CheckStateChanged;
    }
}

In order to replace the default group cell with the custom one, it is necessary to subscribe to the CreateCell event:

private void radGridView1_CreateCell(object sender, Telerik.WinControls.UI.GridViewCreateCellEventArgs e)
{
    if (e.CellType == typeof(GridGroupContentCellElement))
    {
        e.CellElement = new CustomGridGroupContentCellElement(e.Column, e.Row);
    }
}

When a cell’s value is changed in the GridViewCheckBoxColumn the group row’s check box should be updated as well:

private void radGridView1_CellValueChanged(object sender, GridViewCellEventArgs e)
{
    if (e.Column.Name == "Discontinued")
    {
        GridViewGroupRowInfo parentGroup = e.Row.Parent as GridViewGroupRowInfo;
        if (parentGroup != null)
        {
            bool atLeastOneOff = false;
            foreach (GridViewRowInfo row in parentGroup.ChildRows)
            {
                if ((bool)row.Cells["Discontinued"].Value == false)
                {
                    atLeastOneOff = true;
                    break;
                }
            }
            parentGroup.Tag = !atLeastOneOff;
        }
    }
}

You can download a VB and C# project from the following link.

In this article