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

Use Custom Comparer to Speed up the Sorting in RadGridView

Date Posted Product Author
May 21, 2015 RadGridView for WinForms Dimitar Karamfilov

Problem

When sorting the RadGridView logic should retrieve all object properties  by using reflection. This is needed because the sorting must work with different kind of objects and should be able to compare them. Taking the property value with reflection is slow (this can be noted when you have large amount of rows in the grid) and can be avoided by using a custom comparer where the items are directly casted to the respective objects. 

Solution

First, you need to implement the custom comparer class. This class should implement the IComparer<GridViewRowInfo> interface. This interface has only one method called Compare. It takes two arguments and their type is GridViewRowInfo (In general the class should be able to compare two rows and return the result).  
In addition you should have access to the SortDescritors collection of the grid view. This can be achieved by passing it to group comparer constructor. This will allow you to compare the rows according to all columns sort descriptors and the current sort direction. 

The CompareDataItems method should be able to compare all data object properties. This way the user will be able to sort each column.

public class CustomComparer : IComparer<GridViewRowInfo>
{
    private SortDescriptorCollection sortDescriptors;

    public CustomComparer(SortDescriptorCollection sortDescriptors)
    {
        this.sortDescriptors = sortDescriptors;
    }

    public int Compare(GridViewRowInfo x, GridViewRowInfo y)
    {
        GridItem item1 = (GridItem)x.DataBoundItem;
        GridItem item2 = (GridItem)y.DataBoundItem;

        int result = 0;

        for (int i = 0; i < this.sortDescriptors.Count; i++)
        {
            result = this.CompareDataItems(item1, item2, this.sortDescriptors[i].PropertyName, this.sortDescriptors[i].Direction == ListSortDirection.Ascending);

            if (result != 0)
            {
                return result;
            }
        }

        return result;
    }

    private int CompareDataItems(GridItem x, GridItem y, string propertyName, bool ascending)
    {
        int asc = (ascending) ? 1 : -1;

        switch (propertyName)
        {
            case "TextValue":
                return x.TextValue.CompareTo(y.TextValue) * asc;
            case "IntValue":
                return x.IntValue.CompareTo(y.IntValue) * asc;

        }

        return 0;
    }
}

Public Class CustomComparer
    Implements IComparer(Of GridViewRowInfo)

    Private sortDescriptors As SortDescriptorCollection

    Public Sub New(ByVal sortDescriptors As SortDescriptorCollection)
        Me.sortDescriptors = sortDescriptors
    End Sub

    Public Function Compare(ByVal x As GridViewRowInfo, ByVal y As GridViewRowInfo) As Integer Implements IComparer(Of GridViewRowInfo).Compare
        Dim item1 As GridItem = DirectCast(x.DataBoundItem, GridItem)
        Dim item2 As GridItem = DirectCast(y.DataBoundItem, GridItem)

        Dim result As Integer = 0

        For i As Integer = 0 To Me.sortDescriptors.Count - 1
            result = Me.CompareDataItems(item1, item2, Me.sortDescriptors(i).PropertyName, Me.sortDescriptors(i).Direction = ListSortDirection.Ascending)

            If result <> 0 Then
                Return result
            End If
        Next i

        Return result
    End Function

    Private Function CompareDataItems(ByVal x As GridItem, ByVal y As GridItem, ByVal propertyName As String, ByVal ascending As Boolean) As Integer
        Dim asc As Integer = If(ascending, 1, -1)

        Select Case propertyName
            Case "TextValue"
                Return x.TextValue.CompareTo(y.TextValue) * asc
            Case "IntValue"
                Return x.IntValue.CompareTo(y.IntValue) * asc
        End Select

        Return 0
    End Function
End Class

To use the class assign new instance to the SortComparer property:

radGridView1.MasterTemplate.SortComparer = new CustomComparer(this.radGridView1.SortDescriptors);

radGridView1.MasterTemplate.SortComparer = New CustomComparer(Me.radGridView1.SortDescriptors)

You can use the following code to complete the example and test the sorting:

public partial class RadForm1 : Telerik.WinControls.UI.RadForm
{
    Random rnd = new Random();
    BindingList<GridItem> data;

    public RadForm1()
    {
        InitializeComponent();
        data = new BindingList<GridItem>();
        for (int i = 0; i < 100000; i++)
        {
            data.Add(new GridItem("Text " + rnd.Next(100), i));
        }

        radGridView1.DataSource = data;
    }
}

public class GridItem
{
    public string TextValue { get; set; }

    public int IntValue { get; set; }

    public GridItem(string textValue, int intValue)
    {
        this.TextValue = textValue;
        this.IntValue = intValue;
    }
}

Partial Public Class RadForm1
    Inherits Telerik.WinControls.UI.RadForm

    Private rnd As New Random()
    Private data As BindingList(Of GridItem)

    Public Sub New()
        InitializeComponent()
        data = New BindingList(Of GridItem)()
        For i As Integer = 0 To 99999
            data.Add(New GridItem("Text " & rnd.Next(100), i))
        Next i

        radGridView1.DataSource = data

    End Sub
End Class

Public Class GridItem
    Public Property TextValue() As String

    Public Property IntValue() As Integer

    Public Sub New(ByVal textValue As String, ByVal intValue As Integer)
        Me.TextValue = textValue
        Me.IntValue = intValue
    End Sub
End Class

A complete solution in C# and VB.NET can be found here.

In this article