This is a migrated thread and some comments may be shown as answers.

Grouping checkbox

6 Answers 307 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Oliver
Top achievements
Rank 1
Oliver asked on 07 Mar 2012, 04:51 AM
Hi,

in my project I have a RadGridView with all features enable: Sorting, Grouping, etc...

In my grid, I have a GridViewSelectColumn to let my users to select all the rows they want. With this kind of column, I think, the logical pattern was respected by having a checkbox in the header to select/unselect all the rows in the grid. I'm trying to get an answer why this kind of column is missing when you grouping data. What should I do if I group a set of data by date and for a specific date I want to select all the subset items (more than 500 items)???

I'm trying to implement something but I don't know how to acheive it. Actually, I have a problem with the interaction of the groupcheckbox and the rest of the grid. I need to have my groupcheckbox to react the same has the header one, I mean, if I click a on of my groupcheckbox, I need to select all teh group subset and of course, if that mean that all data in the grid is selected after my click, of course the header checkbox should become check. Of course, my groupcheckbox should react to the fact that not all subset data was selected or not by becoming check or not. If the master header checkbox in the header should check all my groupcheckbox and so on...

Please help me, I know I'm not for from the solution ;)

Window1.xaml
------------------
<Window x:Class="RadControlsWpfApp6.Window1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"               
        xmlns:alain="clr-namespace:RadControlsWpfApp6"
  Title="Window1" Height="300" Width="300" WindowState="Maximized" Name="Me">
  <Grid>
        <telerik:RadGridView x:Name="grid" AutoGenerateColumns="False" IsReadOnly="True" RowIndicatorVisibility="Collapsed" SelectionMode="Multiple" PreviewMouseLeftButtonUp="grid_PreviewMouseLeftButtonUp" SelectionChanged="grid_SelectionChanged">
            <telerik:RadGridView.GroupHeaderTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" >
                        <alain:GridViewGroupCheckBox x:Name="GroupCheckBox"/>
                        <TextBlock Margin="5 0" Text="{Binding Group.Key}" />
                    </StackPanel>
                </DataTemplate>
            </telerik:RadGridView.GroupHeaderTemplate>
            <telerik:RadGridView.Columns>
                <telerik:GridViewSelectColumn />
                <telerik:GridViewDataColumn DataMemberBinding="{Binding Path=LastName}" Header="LastName" />
                <telerik:GridViewDataColumn DataMemberBinding="{Binding Path=FirstName}" Header="FirstName" />
            </telerik:RadGridView.Columns>
        </telerik:RadGridView>
    </Grid>
</Window>


Window1.xaml.cs
---------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

using Telerik.Windows.Controls;
using Telerik.Windows.Controls.GridView;
using Telerik.Windows.Data; 

namespace RadControlsWpfApp6
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
           
            AllPersons = new List<Person>();

            AllPersons.Add(new Person() { LastName = "Test2", FirstName = "Test1" });
            AllPersons.Add(new Person() { LastName = "Test1", FirstName = "Test2" });
            AllPersons.Add(new Person() { LastName = "Test2", FirstName = "Test1" });

            grid.ItemsSource = AllPersons;
        }

        public List<Person> AllPersons { get; set; }

        private void grid_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            var senderElement = (FrameworkElement)e.OriginalSource;
            var clickedCell = senderElement.ParentOfType<GridViewHeaderCell>();

            if (clickedCell != null)
            {
                CheckBox chkHeader = clickedCell.Column.Header as CheckBox;
                if (chkHeader != null)
                {
                    IEnumerable<GridViewGroupRow> grpRows = grid.ChildrenOfType<GridViewGroupRow>();
                    GridViewGroupCheckBox.CheckUncheckItems(true, !(bool)chkHeader.IsChecked, grpRows);
                }
            }
        }

        private void grid_SelectionChanged(object sender, SelectionChangeEventArgs e)
        {
            GridViewItemContainerGenerator container = this.grid.ItemContainerGenerator;
                       
            foreach (var oneItem in e.AddedItems)
            {                               
                object obj = container.ContainerFromItem(oneItem);               
            }

            foreach (var oneItem in e.RemovedItems)
            {
            }
        }
    }

    public class Person
    {
        public string LastName { get; set; }
        public string FirstName { get; set; }
    }
}



GridViewGroupCheckBox.xaml
--------------------------------------
<UserControl x:Class="RadControlsWpfApp6.GridViewGroupCheckBox"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="Auto" Width="Auto">
    <Grid>
        <CheckBox x:Name="cbGroup" Click="cbGroup_Click" />
    </Grid>
</UserControl>


GridViewGroupCheckBox.xaml.cs
------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using Telerik.Windows.Controls;
using Telerik.Windows.Controls.GridView;
using Telerik.Windows.Data;

namespace RadControlsWpfApp6
{
    /// <summary>
    /// Interaction logic for GridViewGroupCheckBox.xaml
    /// </summary>
    public partial class GridViewGroupCheckBox : UserControl
    {
        #region Constructors.
        /// <summary>
        /// Costructor.
        /// </summary>
        public GridViewGroupCheckBox()
        {
            InitializeComponent();
            mIsChecked = false;
        }
        #endregion

        #region Public properties.
        public bool IsChecked
        {
            get
            {
                return mIsChecked;
            }
            set
            {
                if (mIsChecked != value)
                {
                    mIsChecked = value;
                    cbGroup.IsChecked = mIsChecked;
                }
            }
        }

        public GridViewGroupRow GroupRow
        {
            get
            {
                return cbGroup.ParentOfType<GridViewGroupRow>();
            }
        }
        #endregion.

        #region Private event handlers.
        /// <summary>
        /// CheckBox click triggered.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>       
        private void cbGroup_Click(object sender, RoutedEventArgs e)
        {
            mIsChecked = (bool)(sender as CheckBox).IsChecked;
            applyChangesOnGrid(sender as CheckBox);
        }
        #endregion

        #region Private medthods.
        /// <summary>
        /// Apply changes
        /// </summary>
        /// <param name="pCheckBox"></param>
        private void applyChangesOnGrid(CheckBox pCheckBox)
        {
            CheckUncheckItems(false, (bool)pCheckBox.IsChecked, this.GroupRow);

            IEnumerable<GridViewGroupRow> groupsChildRows = this.GroupRow.ChildrenOfType<GridViewGroupRow>();
            CheckUncheckItems(false, (bool)pCheckBox.IsChecked, groupsChildRows);
        }

        /// <summary>
        /// Select/unselect all items in a group.
        /// </summary>
        /// <param name="pCheck">TRUE to select or FALSE to unselect.</param>
        /// <param name="pGroupRows">Group of rows.</param>
        static public void CheckUncheckItems(bool pIsInAllSelectionMode, bool pCheck, GridViewGroupRow pGroupRows)
        {
            if (!pIsInAllSelectionMode)
            {
                var theGrid = pGroupRows.ParentOfType<GridViewDataControl>();
                IEnumerable<CheckBox> allCheckBox = pGroupRows.ChildrenOfType<CheckBox>();

                if (allCheckBox != null)
                {
                    foreach (CheckBox oneCheckBox in allCheckBox)
                    {
                        oneCheckBox.IsChecked = pCheck;
                    }
                }

                if (theGrid != null)
                {
                    foreach (var item in pGroupRows.Items)
                    {
                        if (pCheck)
                        {
                            theGrid.SelectedItems.Add(item);
                        }
                        else
                        {
                            theGrid.SelectedItems.Remove(item);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// For each sub group rows, select/unselect all items in a group.
        /// </summary>       
        /// <param name="pCheck">TRUE to select or FALSE to unselect.</param>
        /// <param name="pGroupsRows">List of groups rows.</param>
        static public void CheckUncheckItems(bool pIsInAllSelectionMode, bool pCheck, IEnumerable<GridViewGroupRow> pGroupsRows)
        {
            foreach (GridViewGroupRow oneGroupRow in pGroupsRows)
            {
                CheckUncheckItems(pIsInAllSelectionMode, pCheck, oneGroupRow);
            }
        }
        #endregion

        #region Private declarations.
        private bool mIsChecked;
        #endregion
    }
}




Thank's

6 Answers, 1 is accepted

Sort by
0
Maya
Telerik team
answered on 07 Mar 2012, 09:31 AM
Hi Oliver,

You can try adding each of the items in the group to the SelectedItems collection of the grid. It could be something similar to:

private void CheckBox_Checked(object sender, RoutedEventArgs e)
        {
            var groupViewModel = (sender as CheckBox).DataContext as GroupViewModel;
            foreach (var item in groupViewModel.Group.Items)
            {
                this.clubsGrid.SelectedItems.Add(item);
            }
        }

As it is in your case, you can try again to find DataContext of the CheckBox and to add the items of the group to the SelectedItems of the parent grid (you can find it through ParentOfType<T>() extension method). 

Kind regards,
Maya
the Telerik team
Sharpen your .NET Ninja skills! Attend Q1 webinar week and get a chance to win a license! Book your seat now >>
0
Oliver
Top achievements
Rank 1
answered on 07 Mar 2012, 04:29 PM
Hi Maya,

this is fine to select or unselect all the the group row. If all the rows in my group is selected and I unselect one row, how I can tell my groupcheckbox to reflect the rows selection in my group? I mean, each time I select a row in my group, I have to check or uncheck my groupcheckbox (I need to find which groupcheckbox to check or uncheck). The same logic should be apply for the "Select all" checkbox in the grid header.

PS: With your example, can you tell me if it support to work if I have a multiple columns grouping ?

Thank's
0
Maya
Telerik team
answered on 09 Mar 2012, 11:01 AM
Hi Oliver,

Based on the information provided, I get the impression that you want to achieve functionality similar to our GridViewSelectColumn - to be able to select all items in the group when checking the CheckBox in the group row and uncheck it when a single item is unselected. Am I right or am I missing something ?  
If so, my recommendation would be to handle this entirely logic in your model and view model. For example you can expose property in your business object responsible for holding the information whether an item is selected or not and expose property for the group rows that will be set to "True"/ "False" depending on the number of selected items in the group (whether they are all selected or not). 

Regards,
Maya
the Telerik team
Sharpen your .NET Ninja skills! Attend Q1 webinar week and get a chance to win a license! Book your seat now >>
0
Oliver
Top achievements
Rank 1
answered on 09 Mar 2012, 03:47 PM
Hello Maya,

THAT'S EXACTLY WHAT I NEED!!! The question is: Why when we have a GridViewSelectColumn, automatically a checkbox are present in the column header to check/uncheck all data in the grid and this logic are not the same for the grouping, I mean check/uncheck all the date for a specific group?!?

On my side, modifying the bussiness logic in a short time is not possible that's why I have to work with the grid directly (Maybe you ca provide us a small demo on how to do it in a near future. Actually I create a DataTemplate for my group header with a checkbox but it's not fully functionnal. ONE OF THE PROBLEM I have is when I click on the column header checkbox, with the logic I implemented, if I click on the column header checkbox, SOME of the non-visible datatemplate are uncheck, if I expand a group of one of an uncheck datatemplate checkbox, I can see clearly that all the sub-detail was check and sundently, the datatemplate checkbox become check, it's look like it's a refesh issue...

PS: Why the RadGridView don't have properties like: CurrentRow, SelectedRow  of type GridViewRow??? How we can get a GridViewRow attach to an object item in the grid???

Thank's
0
Vlad
Telerik team
answered on 14 Mar 2012, 09:36 AM
Hello,

We've never received such requests and that is why we do not have such feature (selection for group items). 

PS: This completely against WPF paradigm - UI elements should be reused (recycled) and everything should be virtual. Only data related properties should be used (CurrentItem, SelectedItem, etc.).

Kind regards,
Vlad
the Telerik team
Sharpen your .NET Ninja skills! Attend Q1 webinar week and get a chance to win a license! Book your seat now >>
0
Oliver
Top achievements
Rank 1
answered on 16 Mar 2012, 01:56 PM
Hi,

now I think you have a request ;)

Thank's
Tags
GridView
Asked by
Oliver
Top achievements
Rank 1
Answers by
Maya
Telerik team
Oliver
Top achievements
Rank 1
Vlad
Telerik team
Share this question
or