Using IComparer IComparable for Sorting in WPF



IComparer / IComparable are interfaces used to compare two objects. The implementing class has to define the logic for sorting. It provides a way to customize the sort order of a collection.

Implementation of IComparable in WPF. Here, we implement the CompareTo method and sort the Emp objects based on Age property.

Just create a sample WPF application and paste the code as seen below :

Emp class implements IComparable which defines the sort logic.

namespace WpfApplication1 

///
/// Interaction logic for MainWindow.xaml 
/// 
public partial class MainWindow : Window 

    public MainWindow() 
    { 
        InitializeComponent();
        List empList = new List(); 
        empList.AddRange(new List(){new Emp { Name = "A", Age = 25, Address = "Test StreetA" }, 
        new Emp { Name = "A", Age = 26, Address = "Test StreetA1" }, 
        new Emp { Name = "B", Age = 25, Address = "Test StreetB" }, 
        new Emp { Name = "C", Age = 26, Address = "Test StreetC" }, 
        new Emp { Name = "Z", Age = 25, Address = "Test StreetZ" }, 
        new Emp { Name = "D", Age = 26, Address = "Test StreetD" }}); 
        empList.Sort();
        } 
}
 
public class Emp 

    public string Name { getset; } 
    public int Age { getset; } 
    public string Address { getset; } 
}

 public class Emp : IComparable 

    public string Name { getset; } 
    public int Age { getset; } 
    public string Address { getset; }
 
    #region IComparable Members
    public int CompareTo(Emp other) 
    { 
        // Sort based on Age 
        if (this.Age > other.Age) 
        { 
            return 1
        } 
        else if (other.Age > this.Age) 
             return -1
        else 
             return 0;
        }
        #endregion 
    } 
}

Note:

List test = new List();
test.Add("B");
test.Add("C");
test.Add("A");
test.Sort();

This will work because by default List and Array implement IComparable.

But the example below won't work.

public class Emp 

    public string Name { getset; } 
}
// Sorting using IComparable based Age ascending order 
List empList = new List(); 
empList.AddRange(new List(){new Emp { Name = "C25"}, 
                            new Emp { Name = "B35"},
                            new Emp { Name = "A15"}});
empList.Sort();

C# compiler is not smart enough to figure out which instance of type "Emp" should come first etc.

IComparer interface:

But sometimes, we may need to sort a list of objects when the class does not implement IComparable<> interface and also we may need various kinds of sorting on that class like:

  1. Sort Emp by Age in Ascending Order
  2. Sort Emp by Age in Descending Order
  3. Sort Emp by Name
To solve this problem, .NET provides a special interface called IComparer<> which has a method Compare(), takes two object parameters X, Y and returns an int. Use of IComparer<> interface tells List how exactly you want to sort.

namespace WpfApplication1
{
    ///

     /// Interaction logic for MainWindow.xaml 
    /// 
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            // Sorting using IComparable based Age ascending order 
            List empList = new List();
            empList.AddRange(new List(){new Emp { Name = "A25", Age = 25, Address = "Test StreetA25" }, 
                                        new Emp { Name = "B35", Age = 35, Address = "Test StreetB35" }, 
                                        new Emp { Name = "C15", Age = 15, Address = "Test StreetC15" }, 
                                        new Emp { Name = "D45", Age = 45, Address = "Test StreetD45" }, 
                                        new Emp { Name = "E5", Age = 5, Address = "Test StreetE5" }});
            // Default sort as defined by IComparable 
            empList.Sort();
            foreach (dynamic emp in empList)
            {
                string listTemp = emp.Name + "-" + emp.Age + "-" + emp.Address;
                myListBox.Items.Add(listTemp);
            }
            // Create IComparer instance 
            Emp_SortByAgeByDescendingOrder descSort = new Emp_SortByAgeByDescendingOrder();
            // Specify the type 
            empList.Sort(descSort);
            foreach (dynamic emp in empList)
            {
                string listTemp = emp.Name + "-" + emp.Age + "-" + emp.Address;
                myListBox1.Items.Add(listTemp);
            }
        }
    }
    public class Emp : IComparable
    {
        public string Name { getset; }
        public int Age { getset; }
        public string Address { getset; }
        public int CompareTo(Emp other)
        {
            // Sort based on Age 
            if (this.Age > other.Age)
            {
                return 1;
            }
            else if (other.Age > this.Age)
                return -1;
            else
                return 0;
        }
    }
    class Emp_SortByAgeByDescendingOrder : IComparer
    {
        #region IComparer Members
        public int Compare(Emp x, Emp y)
        {
            if (x.Age < y.Age) return 1;
            else if (x.Age > y.Age) return -1;
            else return 0;
        }
        #endregion
    }
    class Emp_SortByName : IComparer
    {
        #region IComparer Members
        public int Compare(Emp x, Emp y)
        {
            return string.Compare(x.Name, y.Name);
        }

        #endregion

    }
}

Special case : If we have both IComparer and IComparable implemented Sort will take place based on IComparer logic first and then followed
by IComparable logic.

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        List empList = new List();
        empList.AddRange(new List(){new Emp { Name = "A", Age = 25, Address = "Test StreetA25" }, 
                                    new Emp { Name = "A", Age = 35, Address = "Test StreetB35" }, 
                                    new Emp { Name = "B", Age = 15, Address = "Test StreetC15" }, 
                                    new Emp { Name = "B", Age = 45, Address = "Test StreetD45" }, 
                                    new Emp { Name = "C", Age = 5, Address = "Test StreetE5" }});
        // Create IComparer instance 
        // IComparer sorts by Name asc 
        // IComparable sorts by Age desc 
        // Sort should be Name asc and Age desc 
        Emp_SortByName descSort = new Emp_SortByName();
        // Specify the type 
        empList.Sort(descSort);
        foreach (dynamic emp in empList)
        {
            string listTemp = emp.Name + "-" + emp.Age + "-" + emp.Address;
            myListBox1.Items.Add(listTemp);
        }
    }
}
 
public class Emp : IComparable
{
    public string Name { getset; }
    public int Age { getset; }
    public string Address { getset; }
    public int CompareTo(Emp other)
    {
        // Sort based on Age 
        if (this.Age > other.Age)
        {
            return 1;
        }
        else if (other.Age > this.Age)
            return -1;
        else
            return 0;
    }
}
 
class Emp_SortByName : IComparer
{
    #region IComparer Members
    public int Compare(Emp x, Emp y)
    {
        return string.Compare(x.Name, y.Name);
    }
    #endregion
}


Happy Reading...