CheckBox selection column in a RadGridView

17 posts, 0 answers
  1. Alexandru
    Alexandru avatar
    4 posts
    Member since:
    Apr 2012

    Posted 15 Dec 2014 Link to this post

    hi,

    in a winforms app, i am using a RadGridView with MultiSelect = true and i am trying to create a column with check-boxes that will be checked for each row that is selected.
    i want this column to work in both ways:
      1) the check-boxes should update themselves each time the list of selected rows is changed.
      2) the user should be able to select additional rows by checking the check-boxes in this column.

    currently i was able to implement the first request (the check-boxes are updating themselves according to the selected rows), but not the second one.

    i subscribed to the SelectionChanged event of the grid, i unchecked the previously selected check-boxes and then checked the ones from the currently selected rows. here is the code:


            private readonly List<GridViewRowInfo> previouslySelectedRows = new List<GridViewRowInfo>();

            private void HandleGridSelectionChanged(object sender, EventArgs e)
            {
                    UnCheckPreviouslySelectedRows();
                    CheckCurrentlySelectedRows();
                    StoreCurrentlySelectedRows();
            }

            private void UnCheckPreviouslySelectedRows()
            {
                foreach (GridViewRowInfo row in previouslySelectedRows)
                {
                    row.Cells["Select"].Value = false;
                }
            }

            private void CheckCurrentlySelectedRows()
            {
                IEnumerable<GridViewCellInfo> cells = radGridView1.SelectedRows
                    .Select(x => x.Cells["Select"]);

                foreach (GridViewCellInfo cell in cells)
                {
                    cell.Value = true;
                }
            }

            private void StoreCurrentlySelectedRows()
            {
                previouslySelectedRows.Clear();
                previouslySelectedRows.AddRange(radGridView1.SelectedRows);
            }

    did someone implement something similar?
    can someone help me with the second task (to let the user select/unselect rows by checking/unchecking the check-boxes)?

    thank you,
    alez

  2. Hristo
    Admin
    Hristo avatar
    1087 posts

    Posted 17 Dec 2014 Link to this post

    Hello Alexandru,

    Thank you for writing.

    The code you provided appears to be working properly. If you would like to keep your logic and additionally allow the user to select rows by simply changing the checkbox value you should also subscribe to CellBeginEdit event. Then you should cancel it because letting it to execute would interfere with you logic:
    private void radGridView1_CellBeginEdit(object sender, GridViewCellCancelEventArgs e)
    {
        if (this.radGridView1.CurrentColumn.Name == "Select")
        {
            e.Cancel = true;
        }
    }

    Please bear in mind that multiple selection by design works by holding the Ctrl key. I have attached a .gif file demonstrating the behavior of the grid on my side.

    Hope this helps. Should you have further questions do not hesitate to write back.

    Regards,
    Hristo
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  3. Srividya
    Srividya avatar
    2 posts
    Member since:
    Mar 2016

    Posted 07 Oct 2016 Link to this post

    Hi Team,

    I have different case in the multi level grid view.

    Parent 1

      Child 1

        Child 1-1

        Child 1-2

        Child 1-3

      Child 2

        Child 2-1

         Child 2-2

    Parent 2

    ect....

    in above multi level grid check box is placed at the last column

    My scenario:

    1. if we check the parent 1->Child 1  then all corresponding child (child 1-1,child 1-2)check boxes should be checked.

    2. if we uncheck the child 1-1 then child 1 should be uncheck as well as child 1-2 should be in previous state because we haven't touch it ;)

    3. if we select a new row I mean parent 2-> child 1-1 then should work above 2 scenarios

    4.if we uncheck and check the same row the above first 2 scenarios should work

     

    Please help me out with a simple solution I tried with so many ways by keeping Boolean variables in the code..but no use of it

  4. Hristo
    Admin
    Hristo avatar
    1087 posts

    Posted 07 Oct 2016 Link to this post

    Hi Srividya,

    Thank you for writing.

    You can achieve this task by iterating the hierarchy and data rows for the different hierarchy templates: Iterating the child rows collection of a chosen parent row in hierarchy RadGridView.

    A suitable place for performing this operation is the handler of the CellValueChanged event. Please check my code snippet below: 
    bool suspendEvent = false;
    private void radGridView1_CellValueChanged(object sender, GridViewCellEventArgs e)
    {
        if (!suspendEvent && e.Column.Name == "IsValid")
        {
            List<GridViewHierarchyRowInfo> parents = new List<GridViewHierarchyRowInfo>();
            GridViewHierarchyRowInfo parent = e.Row.Parent as GridViewHierarchyRowInfo;
            while (parent != null)
            {
                parents.Add(parent);
                parent = parent.Parent as GridViewHierarchyRowInfo;
            }
     
            suspendEvent = true;
            foreach (GridViewHierarchyRowInfo p in parents)
            {
                if (p.Views.Count > 0)
                {
                    p.Cells["IsValid"].Value = this.CheckCellsForLevel(p.Views[0]);
                }
            }
     
            GridViewHierarchyRowInfo hierarchyRow = e.Row as GridViewHierarchyRowInfo;
            if (hierarchyRow != null)
            {
                Queue<GridViewHierarchyRowInfo> children = new Queue<GridViewHierarchyRowInfo>();
                children.Enqueue(hierarchyRow);
     
                while (children.Count > 0)
                {
                    GridViewHierarchyRowInfo current = children.Dequeue();
                    foreach (GridViewRowInfo row in current.ChildRows)
                    {
                        row.Cells["IsValid"].Value = e.Value;
                        if (row is GridViewHierarchyRowInfo)
                        {
                            children.Enqueue((GridViewHierarchyRowInfo)row);
                        }
                    }
                }
            }
     
            suspendEvent = false;
        }
    }
     
    private bool CheckCellsForLevel(GridViewInfo template)
    {
        foreach (GridViewRowInfo rowInfo in template.Rows)
        {
            if ((bool)rowInfo.Cells["IsValid"].Value == false)
            {
                return false;
            }
        }
     
        return true;
    }

    Please note that in order to illustrate the idea and to make the example simpler in all of my grid templates I am having a GridViewCheckBoxColumn with the name IsValid. You may need to alter this to access the proper cells in your actual project. I am also sending you a short video showing the result on my end.

    I hope this helps. Should you have further questions please do not hesitate to write back.

    Regards,
    Hristo Merdjanov
    Telerik by Progress
    Check out the Windows Forms project converter, which aids the conversion process from standard Windows Forms applications written in C# or VB to Telerik UI for WinForms. For more information check out this blog post and share your thoughts.
  5. Srividya
    Srividya avatar
    2 posts
    Member since:
    Mar 2016

    Posted 10 Oct 2016 in reply to Hristo Link to this post

    Hi Hristo,

    The above code is working as expected thank you so much.....

    :)

    Regards,

    Srividya

  6. swarupa
    swarupa avatar
    14 posts
    Member since:
    Aug 2016

    Posted 10 Oct 2016 Link to this post

    Hi Hristo,

    The above code is useful for one of my requirements.

    I am using telerik 2013 version.

    I need to display Checkbox in the header row for all the three level gridview, so that I can check and uncheck the checkboxes in the data rows automatically when the header checkbox is checked or unchecked.

    In 2013 version we don't have Gridviewcheckboxcolumn.EnableHeaderCheckBox Property.

    So I have used the following code, which I have taken from Telerik forums to enable the header check boxes in all the

    three levels gridview. Its working fine in the first level gridview, but it is not working for second and third levels gridview.

     

    public class CheckBoxHeaderCell : GridHeaderCellElement
    {
    #region Fields
    private RadCheckBoxElement checkbox;
    private int suspendNotificationCount = 0;
    private bool suspendProcessingToggleStateChanged;
    #endregion
    #region Initialization
    public CheckBoxHeaderCell(GridViewColumn column, GridRowElement row)
    : base(column, row)
    {
    }
    protected override void InitializeFields()
    {
    base.InitializeFields();
    this.DrawText = false;
    }
    public override void Initialize(GridViewColumn column, GridRowElement row)
    {
    base.Initialize(column, row);
    column.AllowSort = false;
    }
    protected override void DisposeManagedResources()
    {
    this.checkbox.ToggleStateChanged -= new StateChangedEventHandler(checkbox_ToggleStateChanged);
    base.DisposeManagedResources();
    }
    protected override void CreateChildElements()
    {
    base.CreateChildElements();
    this.checkbox = new RadCheckBoxElement();
    this.checkbox.ToggleStateChanged += new StateChangedEventHandler(checkbox_ToggleStateChanged);
    this.Children.Add(checkbox);
    } #endregion
    #region Properties
    protected override Type ThemeEffectiveType
    {
    get
    {
    return typeof(GridHeaderCellElement);
    }
    }
    public override object Value
    {
    get
    {
    return Convert.ToBoolean(this.RowInfo.Tag);
    }
    set
    {
    this.RowInfo.Tag = value;
    }
    } #endregion
    #region Methods
    public void SetCheckBoxState(Telerik.WinControls.Enumerations.ToggleState state)
    {
    suspendProcessingToggleStateChanged = true;
    this.checkbox.ToggleState = state;
    suspendProcessingToggleStateChanged = false;
    }

    protected override void SetContentCore(object value)
    {
    base.SetContentCore(value);
    this.suspendNotificationCount++;
    if (this.RowInfo.Tag != null)
    {
    this.checkbox.ToggleState = (bool)value ? ToggleState.On : ToggleState.Off;
    }
    else
    {
    this.checkbox.ToggleState = ToggleState.Off;
    }
    this.checkbox.TextElement.Text = this.Text;
    this.suspendNotificationCount--;
    }
    public override bool IsCompatible(GridViewColumn data, object context)
    {
    return data.Name == "Select" && context is GridTableHeaderRowElement
    && base.IsCompatible(data, context);
    }
    #endregion
    #region Event Handlers
    private void checkbox_ToggleStateChanged(object sender, StateChangedEventArgs args)
    {
    if (!suspendProcessingToggleStateChanged)
    {
    for (int i = 0; i < this.GridControl.Rows.Count; i++)
    {
    this.GridControl.Rows[i].Cells[this.ColumnIndex].Value = this.checkbox.IsChecked;
    }
    }

    } #endregion
    #region Layout
    protected override SizeF ArrangeOverride(SizeF finalSize)
    {
    SizeF size = base.ArrangeOverride(finalSize);
    RectangleF rect = GetClientRectangle(finalSize);
    this.checkbox.Arrange(new RectangleF((finalSize.Width - this.checkbox.DesiredSize.Width) / 2, (rect.Height - 20) / 2, 20, 20));
    return size;
    } #endregion }

    private void DgSearchBdPortsResult_CreateCell(object sender, Telerik.WinControls.UI.GridViewCreateCellEventArgs e)
    {
    if (e.Row is GridTableHeaderRowElement && e.Column.HeaderText == "Select All")
    {
    e.CellElement = new CheckBoxHeaderCell(e.Column, e.Row);
    }

    }

     

    private void DgSearchBdPortsResult_ValueChanged(object sender, EventArgs e)
    {
    DgSearchBdPortsResult.EndEdit();

    }

    Thanks And Regards,

    Swarupa

     

  7. Hristo
    Admin
    Hristo avatar
    1087 posts

    Posted 10 Oct 2016 Link to this post

    Hello Swarupa,

    Thank you for writing back.

    I am glad that the suggested approach is working well in your project. Regarding the header checkbox please note that the KB solution as stated here and our latter implementation handles the rows from a single template.

    When you have the grid created in a hierarchy the columns on the various levels may be completely different. If you want this header checkbox to be responsible for rows located in child templates you need to handle it separately. You can alter the solution from the KB article to cope with the hierarchy following an approach as the one discussed here.

    I hope this helps. Should you have further questions please do not hesitate to write back.

    Regards,
    Hristo Merdjanov
    Telerik by Progress
    Check out the Windows Forms project converter, which aids the conversion process from standard Windows Forms applications written in C# or VB to Telerik UI for WinForms. For more information check out this blog post and share your thoughts.
  8. Pavel
    Pavel avatar
    32 posts
    Member since:
    Sep 2016

    Posted 19 Oct 2016 Link to this post

    Sorry for bumping an old thread, but this is the exact same thing I am trying to do.

    I tried subscribing to the CellBeginEdit event, but as soon as I click the checkbox, all the rows get deselected. What are the ppoperties that my RadGrid and my columns need to have in order to make it work?

  9. Hristo
    Admin
    Hristo avatar
    1087 posts

    Posted 20 Oct 2016 Link to this post

    Hi Pavel,

    Thank you for writing.

    I am not sure what exactly is your scenario. Can you please provide more details about your task. A general code snippet demonstrating your local setup would also help.

    Looking forward to your reply.

    Regards,
    Hristo Merdjanov
    Telerik by Progress
    Check out the Windows Forms project converter, which aids the conversion process from standard Windows Forms applications written in C# or VB to Telerik UI for WinForms. For more information check out this blog post and share your thoughts.
  10. Thanh
    Thanh avatar
    8 posts
    Member since:
    Sep 2017

    Posted 03 Nov Link to this post

    Hello,

    I have another case related to the relationship of "Select All" checkbox and hierarchy checkbox.

    I have a sample gridview, please note that the gridview just has only 1 parent row as below:

    ==========================================================

    (cb#1) Select All checkbox   |   Column A   |   Column B   |   ...

    (cb#2) Parent

         (cb#3) Child 1

              (cb#4) Child 1-1

              Child 1-2

              Child 1-3

         Child 2

              Child 2-1

              Child 2-2

    ...

    ==========================================================

    The requirement rules are:

    1. Check on Select All (cb#1) checkbox > All checkboxes will be checked

    2. Check on Parent (cb#2) checkbox > All children checkboxes will be checked

    3. Uncheck a child checkbox > Keep the state of its parent checkbox, but the state of Select All (cb#1) must be changed to unchecked.

     

    My problem is the rule #3, please see the reproduce steps below:

    1. Check on cb#1, so all checkboxes will be checked

    2. Uncheck cb#4, as the requirement, keep the cb#2 and cb#3 as checked, but the cb#1 should be unchecked.

     

    By default,

    - The cb#1 and cb#2 has the relationship.

    - The cb#2 and cb#3 and cb#4 has the relationship.

    I don't know how to implement the relationship of cb#1 and cb#3 / cb#4, since the children checkboxes just have the relationship with its parent, and the Select All checkbox jus have the relationship with the highest parent of gridview.

    Please advice! Thanks so much!

     

    Best regards,

    THANH

     

  11. Hristo
    Admin
    Hristo avatar
    1087 posts

    Posted 03 Nov Link to this post

    Hi Thanh,

    Thank you for writing.

    I would like to clarify that the checkboxes displayed in the header of the column are only responsible for checking and unchecking rows within the same template. The header checkbox can be displayed this way: 
    (this.radGridView1.MasterTemplate.Columns["Select All"] as GridViewCheckBoxColumn).EnableHeaderCheckBox = true;

    Any other logic responsible for checking and unchecking rows from different templates is custom. You can follow the approach I sent in one of my previous posts. You can try removing the logic for checking the parents in the CellValueChanged event handler: 
    bool suspendEvent = false;
    private void radGridView1_CellValueChanged(object sender, GridViewCellEventArgs e)
    {
        if (!suspendEvent && e.Column.Name == "Select All")
        {
            suspendEvent = true;
            GridViewHierarchyRowInfo hierarchyRow = e.Row as GridViewHierarchyRowInfo;
            if (hierarchyRow != null)
            {
                Queue<GridViewHierarchyRowInfo> children = new Queue<GridViewHierarchyRowInfo>();
                children.Enqueue(hierarchyRow);
     
                while (children.Count > 0)
                {
                    GridViewHierarchyRowInfo current = children.Dequeue();
                    foreach (GridViewRowInfo row in current.ChildRows)
                    {
                        row.Cells["Select All"].Value = e.Value;
                        if (row is GridViewHierarchyRowInfo)
                        {
                            children.Enqueue((GridViewHierarchyRowInfo)row);
                        }
                    }
                }
            }
     
            suspendEvent = false;
        }
    }

    I hope this helps. Should you have further questions please do not hesitate to write back.

    Regards,
    Hristo
    Progress Telerik
    Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  12. Thanh
    Thanh avatar
    8 posts
    Member since:
    Sep 2017

    Posted 05 Nov in reply to Hristo Link to this post

    Hi Hristo,

    Thanks for your reply. I'm sorry for lack of information so that the solution you provided cannot resolve my problem.

    Please see my detail information below:

    1. I have a sample gridview has 2 column, see attachment #1:

         - The first column is "IsSelected" column. It's a GridViewCheckBoxColumn type and it has no HeaderText value. I've already applied EnableHeaderCheckBox for this column, so that the system will automatically generate a header checkbox column, I will call it a Select All checkbox.

         - The second column is "Level" column, it's simply a GridViewTextBoxColumn type. Please note that the level 0 is the highest level, it is the parent of all other levels.

    2. When I click on Select All checkbox, all the checkboxes will be checked, see attachment #2.

    3. This is my problem. When I click on the checkbox of level 3.1, see the result in attachment #3. What I expect is the result in attachment #4, I want the Select All checkbox will be unchecked, but the parent checkboxes of level 3.1, include the checkbox of level 3 and the checkbox of level 0 will be kept as "checked" state.

     

    All the checkboxes in "IsSelected" column, include the Select All checkbox, have the same GridViewCheckBoxColumn type and all of the rows, include the header row, have the same GridViewHierarchyRowInfo type. That's why when I click on the checkbox of level 3.1, I have no idea to detect the Select All checkbox to update its state. And I recognized the Select All checkbox and the checkbox of level 0 has the relationship, they always have the same state, I afraid if the Select All checkbox is unchecked, the checkbox of level 0 is unchecked too.

     

    Please advice! Thanks a lot!

     

    Regards,

    THANH

  13. Thanh
    Thanh avatar
    8 posts
    Member since:
    Sep 2017

    Posted 08 Nov Link to this post

    Hello,

    I'm still looking forward to hearing the good news.

    Please help!

     

    Thanks and Best regards,

    THANH

  14. Dess
    Admin
    Dess avatar
    2222 posts

    Posted 08 Nov Link to this post

    Hello, Thanh,

    Thank you for writing.  

    The header checkbox is designed to control the toggle state of the cells in the GridViewCheckBoxColumn for the same template. Hence, if you uncheck the header checkbox, all rows will be unchecked as well and vice versa. This is desired behavior. If you need to customize this default behavior, I would recommend you to create a custom GridCheckBoxHeaderCellElement and add your own RadCheckBoxElement with which you can fully manage the ToggleState according to your custom requirement. Here is a sample code snippet demonstrating how to add a custom checkbox and toggle the rows for the parent template:
    public RadForm1()
    {
        InitializeComponent();
     
        DataTable dt = new DataTable();
        dt.Columns.Add("IsActive", typeof(bool));
        dt.Columns.Add("Name", typeof(string));
     
        for (int i = 0; i < 5; i++)
        {
            dt.Rows.Add(false, "Item" + i);
        }
        this.radGridView1.CreateCell += radGridView1_CreateCell;
        this.radGridView1.DataSource = dt;
        this.radGridView1.AutoSizeColumnsMode = Telerik.WinControls.UI.GridViewAutoSizeColumnsMode.Fill;
    }
     
    private void radGridView1_CreateCell(object sender, GridViewCreateCellEventArgs e)
    {
        if (e.CellType == typeof(GridCheckBoxHeaderCellElement))
        {
            e.CellElement = new CustomGridCheckBoxHeaderCellElement(e.Column, e.Row);
        }
    }
     
    public class CustomGridCheckBoxHeaderCellElement : GridCheckBoxHeaderCellElement
    {
        public CustomGridCheckBoxHeaderCellElement(GridViewColumn column, GridRowElement row)
            : base(column, row)
        {
        }
     
        RadCheckBoxElement myCheckBoxElement = new RadCheckBoxElement();
     
        protected override void CreateChildElements()
        {
            base.CreateChildElements();
     
            myCheckBoxElement.ToggleStateChanged += myCheckBoxElement_ToggleStateChanged;
            this.Children.Add(myCheckBoxElement);
        }
     
        private void myCheckBoxElement_ToggleStateChanged(object sender, StateChangedEventArgs args)
        {
            this.GridControl.BeginUpdate();
            this.RowInfo.Tag = args.ToggleState;
     
            foreach (GridViewRowInfo row in this.GridControl.Rows)
            {
                if (row.HierarchyLevel == 0)
                {
                    row.Cells["IsActive"].Value = args.ToggleState;
                }
            }
            this.GridControl.EndUpdate();
        }
     
        public override void SetContent()
        {
            base.SetContent();
            myCheckBoxElement.ToggleStateChanged -= myCheckBoxElement_ToggleStateChanged;
            if (this.RowInfo.Tag != null)
            {
                myCheckBoxElement.ToggleState = (ToggleState)this.RowInfo.Tag;
            }
            myCheckBoxElement.ToggleStateChanged += myCheckBoxElement_ToggleStateChanged;
        }
    }

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

    I hope this information helps. Should you have further questions I would be glad to help.
     
    Regards,
    Dess
    Progress Telerik
    Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  15. Thanh
    Thanh avatar
    8 posts
    Member since:
    Sep 2017

    Posted 09 Nov Link to this post

    Hello Dess,

    I really appreciate your help.

    Your solution is amazing.

     

    Thanks and Best regards,

    THANH

  16. Deepak
    Deepak avatar
    21 posts
    Member since:
    May 2016

    Posted 1 day and 13 hours ago Link to this post

    Hello,

    I have a GridView with the first column as checkbox column. I need to select only one row at a time. If other row is being selected then the checkbox from the previous row should be removed.

    Is it possible to check only one checkbox at a time? 

     

    Regards,

    Deepak

  17. Dess
    Admin
    Dess avatar
    2222 posts

    Posted 1 day and 11 hours ago Link to this post

    Hello, Deepak,

    Thank you for writing.  

    In order to cover your scenario, you can subscribe to the CurrentRowChanging event where you have access to the previously and newly selected row. Thus, you can manipulate the value of the boolean cell. Here is a sample code snippet which result is illustrated in the attached gif file:  
    public RadForm1()
    {
        InitializeComponent();
        this.radGridView1.CurrentRowChanging += radGridView1_CurrentRowChanging;
        DataTable dt = new DataTable();
        dt.Columns.Add("IsActive", typeof(bool));
        dt.Columns.Add("Id", typeof(int));
        dt.Columns.Add("Name", typeof(string));
        for (int i = 0; i < 10; i++)
        {
            dt.Rows.Add(false, i, "Item" + i);
        }
        this.radGridView1.DataSource = dt;
        this.radGridView1.AutoSizeColumnsMode = Telerik.WinControls.UI.GridViewAutoSizeColumnsMode.Fill;         
    }
     
    private void radGridView1_CurrentRowChanging(object sender, Telerik.WinControls.UI.CurrentRowChangingEventArgs e)
    {
        if (e.NewRow != null)
        {
            e.NewRow.Cells["IsActive"].Value = true;
        }
        if (e.CurrentRow != null)
        {
            e.CurrentRow.Cells["IsActive"].Value = false;
        }
    }


    I hope this information helps. Should you have further questions I would be glad to help.
     
    Regards,
    Dess
    Progress Telerik
    Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
Back to Top