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

How to Create a Header CheckBox in VirtualGrid

Environment

Product Version Product Author
2019.1.219 RadVirtualGrid for WinForms Desislava Yordanova

Description

This article aims to show you how to create a check box column in RadVirtualGrid that contains a check box in the header cell in order to check/uncheck all records.

virtualgrid-header-checkbox

Solution

The CellValueNeeded event in RadVirtualGrid is responsible for populating the grid with data extracting the records from the external data source. The CellValuePushed event is the appropriate place to push the changes to the external source collection.

RadVirtualGrid supports a powerful and flexible mechanism for creating cell types with custom content elements, functionality and properties. A sample approach how to create a check-box column is demonstrated in the following help article: Creating custom cells. We will extend this example to include a header check-box that will check/uncheck all records in RadVirtualGrid.

1. Create a derivative of the VirtualGridHeaderCellElement class and add a RadCheckBoxElement in the CreateChildElements event. In the ToggleStateChanged event of the check-box you should update the toggle state of the records inside the grid:

Custom VirtualGridHeaderCellElement

        public class CustomVirtualGridHeaderCellElement : VirtualGridHeaderCellElement
        {
            RadCheckBoxElement headerCheckBox = new RadCheckBoxElement();

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

            public override bool IsCompatible(int data, object context)
            {
                return data == 3;
            }

            protected override void CreateChildElements()
            {
                base.CreateChildElements();
                this.Children.Add(headerCheckBox);
                this.headerCheckBox.ToggleStateChanged += headerCheckBox_ToggleStateChanged;
            }

            public override void Synchronize()
            {
                base.Synchronize();
                this.headerCheckBox.ToggleStateChanged -= headerCheckBox_ToggleStateChanged;
                headerCheckBox.IsChecked = GetCheckState(this.ColumnIndex);
                this.headerCheckBox.ToggleStateChanged += headerCheckBox_ToggleStateChanged;
            }

            private bool GetCheckState(int columnIndex)
            {
                bool isChecked = true;
                for (int i = 0; i < this.TableElement.RowCount; i++)
                {
                    isChecked &= (bool)((CustomRadVirtualGridElement)this.TableElement.GridElement).GetCellValue(this.headerCheckBox.Checked, i, this.ColumnIndex, this.ViewInfo);
                    if (isChecked == false)
                    {
                        break;
                    }
                }
                return isChecked;
            }

            private void headerCheckBox_ToggleStateChanged(object sender, StateChangedEventArgs args)
            {
                for (int i = 0; i < this.TableElement.RowCount; i++)
                {
                    this.TableElement.GridElement.SetCellValue(this.headerCheckBox.Checked, i, this.ColumnIndex, this.ViewInfo);
                }
                this.TableElement.SynchronizeRows();
            }
        }



     Public Class CustomVirtualGridHeaderCellElement
    Inherits VirtualGridHeaderCellElement

        Private headerCheckBox As RadCheckBoxElement

        Protected Overrides ReadOnly Property ThemeEffectiveType As Type
            Get
                Return GetType(VirtualGridHeaderCellElement)
            End Get
        End Property

        Public Overrides Function IsCompatible(ByVal data As Integer, ByVal context As Object) As Boolean
            Return data = 3
        End Function

        Protected Overrides Sub CreateChildElements()
            MyBase.CreateChildElements()
            headerCheckBox = New RadCheckBoxElement()
            Me.Children.Add(headerCheckBox)
            AddHandler Me.headerCheckBox.ToggleStateChanged, AddressOf headerCheckBox_ToggleStateChanged
        End Sub

        Public Overrides Sub Synchronize()
            MyBase.Synchronize()
            RemoveHandler Me.headerCheckBox.ToggleStateChanged, AddressOf headerCheckBox_ToggleStateChanged
            headerCheckBox.IsChecked = GetCheckState(Me.ColumnIndex)
            AddHandler Me.headerCheckBox.ToggleStateChanged, AddressOf headerCheckBox_ToggleStateChanged
        End Sub

        Private Function GetCheckState(ByVal columnIndex As Integer) As Boolean
            Dim isChecked As Boolean = True

            For i As Integer = 0 To Me.TableElement.RowCount - 1
                isChecked = isChecked And CBool((CType(Me.TableElement.GridElement, CustomRadVirtualGridElement)).GetCellValue(Me.headerCheckBox.Checked, i, Me.ColumnIndex, Me.ViewInfo))

                If isChecked = False Then
                    Exit For
                End If
            Next

            Return isChecked
        End Function

        Private Sub headerCheckBox_ToggleStateChanged(ByVal sender As Object, ByVal args As StateChangedEventArgs)
            For i As Integer = 0 To Me.TableElement.RowCount - 1
                Me.TableElement.GridElement.SetCellValue(Me.headerCheckBox.Checked, i, Me.ColumnIndex, Me.ViewInfo)
            Next

            Me.TableElement.SynchronizeRows()
        End Sub
    End Class  

2. Handle the CreateCellElement event and for the header row (which row index is -1) use the custom header cell:

Apply the custom VirtualGridHeaderCellElement

        private void radVirtualGrid1_CreateCellElement(object sender, VirtualGridCreateCellEventArgs e)
        {
            if (e.ColumnIndex == 3)
            {
                if (e.RowIndex >= 0)
                {
                    e.CellElement = new MyVirtualGridCheckBoxCellElement();
                }
            }

            if (e.RowIndex == -1)
            {
                if (e.ColumnIndex == 3)
                {
                    e.CellElement = new CustomVirtualGridHeaderCellElement();
                }
            }
        }



    Private Sub radVirtualGrid1_CreateCellElement(ByVal sender As Object, ByVal e As VirtualGridCreateCellEventArgs)
        If e.ColumnIndex = 3 Then

            If e.RowIndex >= 0 Then
                e.CellElement = New MyVirtualGridCheckBoxCellElement()
            End If
        End If

        If e.RowIndex = -1 Then

            If e.ColumnIndex = 3 Then
                e.CellElement = New CustomVirtualGridHeaderCellElement()
            End If
        End If
    End Sub   

3. Since you need to iterate the boolean values for all records in the virtual grid in order to determine the value for the header check-box, it is necessary to create a public GetCellValue method for the RadVirtualGridElement. For this purpose, it is necessary to create a custom RadVirtualGrid as follows:

Create a custom RadVirtualGrid


        public class CustomVirtualGrid : RadVirtualGrid
        {
            public override string ThemeClassName
            {
                get
                {
                    return typeof(RadVirtualGrid).FullName;
                }
            }

            protected override RadVirtualGridElement CreateElement()
            {
                return new CustomRadVirtualGridElement();
            }
        }

        public class CustomRadVirtualGridElement : RadVirtualGridElement
        {
            public object GetCellValue(object value, int rowIndex, int columnIndex, VirtualGridViewInfo viewInfo)
            {
                VirtualGridCellValueNeededEventArgs args = new VirtualGridCellValueNeededEventArgs(rowIndex, columnIndex, viewInfo);
                this.OnCellValueNeeded(args);
                return args.Value;
            }
        }



    Public Class CustomVirtualGrid
    Inherits RadVirtualGrid

        Public Overrides Property ThemeClassName As String
            Get
                Return GetType(RadVirtualGrid).FullName
            End Get
            Set(value As String)
                MyBase.ThemeClassName = value
            End Set
        End Property

        Protected Overrides Function CreateElement() As RadVirtualGridElement
            Return New CustomRadVirtualGridElement()
        End Function
    End Class

    Public Class CustomRadVirtualGridElement
    Inherits RadVirtualGridElement

        Public Function GetCellValue(ByVal value As Object, ByVal rowIndex As Integer, ByVal columnIndex As Integer, ByVal viewInfo As VirtualGridViewInfo) As Object
            Dim args As VirtualGridCellValueNeededEventArgs = New VirtualGridCellValueNeededEventArgs(rowIndex, columnIndex, viewInfo)
            Me.OnCellValueNeeded(args)
            Return args.Value
        End Function
    End Class  


A complete solution providing a C# and VB.NET project is available here.

In this article