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

RadGrid Hierarchy & CheckBoxColumn 3 states

9 Answers 261 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Filleau
Top achievements
Rank 1
Filleau asked on 07 Nov 2010, 12:37 PM
Hi,

I'm working with 2010Q2 RadForm in VB.NET 2010

I had trouble achieving what I want with RadGridView (as something like a treeview)

I have one table with
> DadName (as string)
> ChildName (as string)
> ChildAge (as integer)

I would like to have this table in a RadGridView with hierarchy (Dad/Clildren) with a 3 state checkbox Column in order to let users select all/none/some chidren.

Master Template must have 3 columns : CheckBox, DadName, Clidren Count
Child Remplare must have 3 columns : CheckBox, ChildName, ChildAge

- When radgrid is shown for the first time, none off Child Template are displayed
- If DadName have only one Child, I don't whant to display the children template (plus sign) and the checkbox must be checked or unchecked
- if DadName have more than one chlid, user can :
    - Check from Dad Row in order to select or unselect all children
    - Display the Child template hierarchy in order to select some children (In this case the row dad parent checkbox must be on the third state if some clidren are selected, unchecked il none are selected, and checked if all are selected)

Ultimately, I need to retreive all chidren selected for all fathers in a loop.

Thanks for your help

Anthony

9 Answers, 1 is accepted

Sort by
0
Emanuel Varga
Top achievements
Rank 1
answered on 07 Nov 2010, 01:23 PM
Hello Anthony,

Will an example with business objects as data source be ok in your case? Please let me know so that i can prepare something for this.

Best Regards,
Emanuel Varga
0
Filleau
Top achievements
Rank 1
answered on 07 Nov 2010, 01:48 PM
Hello Emanuel

I'm sorry but I not sure to understand what do you mean with "Buisiness Objects"

If my english is good, I think you want to do an example with business data rather than daddy and child.
For me it is not a problem (I wrote my question with daddy and children in order to be simple, but my project is not like this of course)

We can imagine the same thing in others cases. Like "send a gift" to some vendors's clients, or like a folder explorer.

Thanks

Anthony

0
Emanuel Varga
Top achievements
Rank 1
answered on 07 Nov 2010, 02:16 PM
Hello again,

I have prepared something, but it is in C#, can you test it like this? and if everything is ok, i will help you convert it to VB, please let me know.

Best Regards,
Emanuel Varga
0
Emanuel Varga
Top achievements
Rank 1
answered on 07 Nov 2010, 02:19 PM
C# version:
using System;
using System.ComponentModel;
using System.Windows.Forms;
using Telerik.WinControls.UI;
 
public partial class Form1 : Form
{
    private RadGridView radGridView1;
 
    public Form1()
    {
        InitializeComponent();
        this.Controls.Add(radGridView1 = new RadGridView());
 
        radGridView1.Dock = DockStyle.Fill;
        radGridView1.DataBindingComplete += new GridViewBindingCompleteEventHandler(radGridView1_DataBindingComplete);
        radGridView1.CellValueChanged += new GridViewCellEventHandler(radGridView1_CellValueChanged);
        radGridView1.ValueChanged += new EventHandler(radGridView1_ValueChanged);
        radGridView1.ViewCellFormatting += new CellFormattingEventHandler(radGridView1_ViewCellFormatting);
        radGridView1.ChildViewExpanding += new ChildViewExpandingEventHandler(radGridView1_ChildViewExpanding);
    }
 
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
 
        this.radGridView1.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;
        this.radGridView1.DataSource = new ParentsCollection(3);
 
        GridViewTemplate childTemplate = new GridViewTemplate();
        childTemplate.DataSource = new ChildrenCollection();
 
        GridViewRelation childrenRelation = new GridViewRelation(this.radGridView1.MasterTemplate);
        childrenRelation.ChildTemplate = childTemplate;
        childrenRelation.RelationName = "ParentChild";
        childrenRelation.ParentColumnNames.Add("DadName");
        childrenRelation.ChildColumnNames.Add("DadName");
        this.radGridView1.Relations.Add(childrenRelation);
        childTemplate.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;
        childTemplate.BestFitColumns();
        childTemplate.Caption = "Children";
 
        this.radGridView1.MasterTemplate.Templates.Add(childTemplate);
    }
 
    void radGridView1_ValueChanged(object sender, EventArgs e)
    {
        if (radGridView1.CurrentColumn is GridViewCheckBoxColumn)
        {
            radGridView1.EndEdit();
        }
    }
 
    void radGridView1_CellValueChanged(object sender, GridViewCellEventArgs e)
    {
        if (e.Column is GridViewCheckBoxColumn)
        {
            if (e.Value == null)
            {
                return;
            }
 
            if (e.Row.Parent == null)
            {
                foreach (var row in e.Row.ChildRows)
                {
                    // use the row.Tag to perform a programatic change, if the tag is false the parent row will not be updated on child changes
                    row.Tag = false;
                    row.Cells["IsSelected"].Value = radGridView1.CurrentCell.Value;
                    row.Tag = true;
                }
            }
            else if (e.Row.Tag == null || (bool)e.Row.Tag)
            {
                var parentRow = e.Row.Parent as GridViewRowInfo;
                if (parentRow != null)
                {
                    parentRow.Cells["ChildrenSelected"].Value = GetCheckedValueForChildren(parentRow.ChildRows);
                }
            }
        }
    }
 
    private object GetCheckedValueForChildren(GridViewChildRowCollection gridViewChildRowCollection)
    {
        bool? state = null;
        foreach (var row in gridViewChildRowCollection)
        {
            var selectedValue = (bool)row.Cells["IsSelected"].Value;
            if (state.HasValue && state.Value != selectedValue)
            {
                state = null;
                break;
            }
            else
            {
                state = (bool)row.Cells["IsSelected"].Value;
            }
        }
 
        return state;
    }
 
    void radGridView1_DataBindingComplete(object sender, GridViewBindingCompleteEventArgs e)
    {
        var checkBoxColumn = radGridView1.Columns["ChildrenSelected"] as GridViewCheckBoxColumn;
        if (checkBoxColumn != null)
        {
            checkBoxColumn.ThreeState = true;
        }
    }
 
    private void radGridView1_ViewCellFormatting(object sender, CellFormattingEventArgs e)
    {
        GridGroupExpanderCellElement cell = e.CellElement as GridGroupExpanderCellElement;
        if (cell != null && e.CellElement.RowElement is GridDataRowElement)
        {
            if (!IsExpandable(cell.RowInfo))
            {
                cell.Expander.Visibility = Telerik.WinControls.ElementVisibility.Hidden;
            }
            else
            {
                cell.Expander.Visibility = Telerik.WinControls.ElementVisibility.Visible;
            }
        }
    }
 
    private void radGridView1_ChildViewExpanding(object sender, ChildViewExpandingEventArgs e)
    {
        e.Cancel = !IsExpandable(e.ParentRow);
    }
 
    private bool IsExpandable(GridViewRowInfo rowInfo)
    {
        if (rowInfo.ChildRows != null && rowInfo.ChildRows.Count > 0)
        {
            return true;
        }
 
        return false;
    }
}
 
#region Helpers
 
public class Parent
{
    public bool? ChildrenSelected { get; set; }
 
    public string DadName { get; set; }
 
    public Parent(string dadName)
    {
        this.DadName = dadName;
    }
}
 
public class Children
{
    public bool IsSelected { get; set; }
 
    public string DadName { get; set; }
 
    public string ChildName { get; set; }
 
    public Children(string dadName, string childName)
    {
        this.ChildName = childName;
        this.DadName = dadName;
    }
}
 
public class ParentsCollection : BindingList<Parent>
{
    public ParentsCollection(int noItems)
    {
        for (int i = 0; i < noItems; i++)
        {
            this.Add(new Parent("Dad" + i));
        }
    }
}
 
public class ChildrenCollection : BindingList<Children>
{
    public ChildrenCollection()
    {
        this.Add(new Children("Dad1", "Child1"));
        this.Add(new Children("Dad2", "Child1"));
        this.Add(new Children("Dad2", "Child2"));
        this.Add(new Children("Dad2", "Child3"));
    }
}
 
#endregion Helpers
the VB one is coming up...

Best Regards,
Emanuel Varga
0
Filleau
Top achievements
Rank 1
answered on 07 Nov 2010, 02:21 PM
If it is in c# I can use your online converter, but I can understand the mechanism even if it's written in c #.
Your example will help me, but where is the link ?
0
Filleau
Top achievements
Rank 1
answered on 07 Nov 2010, 02:28 PM
Bigs Thanks Emanuel.
I will study your sample.
Best regards
0
Emanuel Varga
Top achievements
Rank 1
answered on 07 Nov 2010, 02:41 PM
Hello again,

Please try this, I've made some minor changes:
Imports System
Imports System.ComponentModel
Imports System.Windows.Forms
Imports Telerik.WinControls.UI
 
Public Class Form1
    Private WithEvents RadGridView1 As RadGridView
 
    Public Sub New()
        InitializeComponent()
        Me.Controls.Add(InlineAssignHelper(RadGridView1, New RadGridView()))
        RadGridView1.Dock = DockStyle.Fill
 
    End Sub
 
    Protected Overrides Sub OnLoad(ByVal e As EventArgs)
        MyBase.OnLoad(e)
 
        Me.RadGridView1.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill
        Me.RadGridView1.DataSource = New ParentsCollection(3)
 
        Dim childTemplate As New GridViewTemplate()
        childTemplate.DataSource = New ChildrenCollection()
 
        Dim childrenRelation As New GridViewRelation(Me.RadGridView1.MasterTemplate)
        childrenRelation.ChildTemplate = childTemplate
        childrenRelation.RelationName = "ParentChild"
        childrenRelation.ParentColumnNames.Add("DadName")
        childrenRelation.ChildColumnNames.Add("DadName")
        Me.RadGridView1.Relations.Add(childrenRelation)
        childTemplate.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill
        childTemplate.BestFitColumns()
        childTemplate.Caption = "Children"
 
        Me.RadGridView1.MasterTemplate.Templates.Add(childTemplate)
    End Sub
 
    Private Sub radGridView1_ValueChanged(ByVal sender As Object, ByVal e As EventArgs) Handles RadGridView1.ValueChanged
        If TypeOf RadGridView1.CurrentColumn Is GridViewCheckBoxColumn Then
            RadGridView1.EndEdit()
        End If
    End Sub
 
    Private Sub radGridView1_CellValueChanged(ByVal sender As Object, ByVal e As GridViewCellEventArgs) Handles RadGridView1.CellValueChanged
        If TypeOf e.Column Is GridViewCheckBoxColumn Then
            If e.Value Is Nothing Then
                Return
            End If
 
            If e.Row.Parent Is Nothing Then
                For Each row As GridViewRowInfo In e.Row.ChildRows
                    ' use the row.Tag to perform a programatic change, if the tag is false the parent row will not be updated on child changes
                    row.Tag = False
                    row.Cells("IsSelected").Value = RadGridView1.CurrentCell.Value
                    row.Tag = True
                Next
            ElseIf e.Row.Tag Is Nothing OrElse CBool(e.Row.Tag) Then
                Dim parentRow = TryCast(e.Row.Parent, GridViewRowInfo)
                If parentRow IsNot Nothing Then
                    parentRow.Cells("ChildrenSelected").Value = GetCheckedValueForChildren(parentRow.ChildRows)
                End If
            End If
        End If
    End Sub
 
    Private Function GetCheckedValueForChildren(ByVal gridViewChildRowCollection As GridViewChildRowCollection) As Object
        Dim state As System.Nullable(Of Boolean) = Nothing
        For Each row As GridViewRowInfo In gridViewChildRowCollection
            If (state Is Nothing And row.Cells("IsSelected").Value Is Nothing) Then
                Continue For
            End If
 
            Dim selectedValue = CBool(row.Cells("IsSelected").Value)
            If state.HasValue AndAlso state.Value <> selectedValue Then
                Return Nothing
                Exit For
            Else
                state = CBool(row.Cells("IsSelected").Value)
            End If
        Next
 
        Return IIf(state is Nothing, False, state)
    End Function
 
    Private Sub radGridView1_DataBindingComplete(ByVal sender As Object, ByVal e As GridViewBindingCompleteEventArgs) Handles RadGridView1.DataBindingComplete
        Dim checkBoxColumn = TryCast(RadGridView1.Columns("ChildrenSelected"), GridViewCheckBoxColumn)
        If checkBoxColumn IsNot Nothing Then
            checkBoxColumn.ThreeState = True
        End If
 
 
        For Each row As GridViewRowInfo In RadGridView1.Rows
            row.Cells("ChildrenSelected").Value = GetCheckedValueForChildren(row.ChildRows)
        Next
 
    End Sub
 
    Private Sub radGridView1_ViewCellFormatting(ByVal sender As Object, ByVal e As CellFormattingEventArgs) Handles RadGridView1.ViewCellFormatting
        Dim cell As GridGroupExpanderCellElement = TryCast(e.CellElement, GridGroupExpanderCellElement)
        If cell IsNot Nothing AndAlso TypeOf e.CellElement.RowElement Is GridDataRowElement Then
            If Not IsExpandable(cell.RowInfo) Then
                cell.Expander.Visibility = Telerik.WinControls.ElementVisibility.Hidden
            Else
                cell.Expander.Visibility = Telerik.WinControls.ElementVisibility.Visible
            End If
        End If
    End Sub
 
    Private Sub radGridView1_ChildViewExpanding(ByVal sender As Object, ByVal e As ChildViewExpandingEventArgs) Handles RadGridView1.ChildViewExpanding
        e.Cancel = Not IsExpandable(e.ParentRow)
    End Sub
 
    Private Function IsExpandable(ByVal rowInfo As GridViewRowInfo) As Boolean
        If rowInfo.ChildRows IsNot Nothing AndAlso rowInfo.ChildRows.Count > 0 Then
            Return True
        End If
 
        Return False
    End Function
    Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, ByVal value As T) As T
        target = value
        Return value
    End Function
 
End Class
 
#Region "Helpers"
 
Public Class Parent
    Public Property ChildrenSelected() As System.Nullable(Of Boolean)
        Get
            Return m_ChildrenSelected
        End Get
        Set(ByVal value As System.Nullable(Of Boolean))
            m_ChildrenSelected = Value
        End Set
    End Property
    Private m_ChildrenSelected As System.Nullable(Of Boolean)
 
    Public Property DadName() As String
        Get
            Return m_DadName
        End Get
        Set(ByVal value As String)
            m_DadName = Value
        End Set
    End Property
    Private m_DadName As String
 
    Public Sub New(ByVal dadName As String)
        Me.DadName = dadName
    End Sub
End Class
 
Public Class Children
    Public Property IsSelected() As Boolean
        Get
            Return m_IsSelected
        End Get
        Set(ByVal value As Boolean)
            m_IsSelected = Value
        End Set
    End Property
    Private m_IsSelected As Boolean
 
    Public Property DadName() As String
        Get
            Return m_DadName
        End Get
        Set(ByVal value As String)
            m_DadName = Value
        End Set
    End Property
    Private m_DadName As String
 
    Public Property ChildName() As String
        Get
            Return m_ChildName
        End Get
        Set(ByVal value As String)
            m_ChildName = Value
        End Set
    End Property
    Private m_ChildName As String
 
    Public Sub New(ByVal dadName As String, ByVal childName As String)
        Me.ChildName = childName
        Me.DadName = dadName
    End Sub
End Class
 
Public Class ParentsCollection
    Inherits BindingList(Of Parent)
    Public Sub New(ByVal noItems As Integer)
        For i As Integer = 0 To noItems - 1
            Me.Add(New Parent("Dad" + i.ToString))
        Next
    End Sub
End Class
 
Public Class ChildrenCollection
    Inherits BindingList(Of Children)
    Public Sub New()
        Me.Add(New Children("Dad1", "Child1"))
        Me.Add(New Children("Dad2", "Child1"))
        Me.Add(New Children("Dad2", "Child2"))
        Me.Add(New Children("Dad2", "Child3"))
    End Sub
End Class
 
#End Region

This should solve your problem, if you have any other questions or comments, please let me know,

Best Regards,
Emanuel Varga
0
Filleau
Top achievements
Rank 1
answered on 07 Nov 2010, 03:42 PM
Your sample is simply perfect !

The last thing, is  I must finaly retreive all children selected.

May I need to do a loop on each RadGridView1.Rows with checkbox column selected (all or partial) and for each of them another loop on the children rows ?
0
Accepted
Emanuel Varga
Top achievements
Rank 1
answered on 07 Nov 2010, 04:09 PM
Hello again,

Yes, sadly you have to do that, or you can keep an internal list, and modify it on each operation, but i would suggest the one you mentioned, on button click, go trough all the parent rows, something like this,
If:
- none, continue;
- partial - go trough all the children and just add the ones selected,
- checked, add all child rows.

If you need any help in doing this please let me know, or if the question has been solved, please mark the question as answered, so that others can find the answers to their questions faster.

Best Regards,
Emanuel Varga

Tags
GridView
Asked by
Filleau
Top achievements
Rank 1
Answers by
Emanuel Varga
Top achievements
Rank 1
Filleau
Top achievements
Rank 1
Share this question
or