LIDOR SYSTEMS

Advanced User Interface Controls and Components

Create custom sort operation in ListView .NET control

January 12, 2010

The IntegralUI ListView control supports predefined sorting based on some predefined types. This is determined by ComparerObjectType property which can have one of these values: Double, Integer and String. Although, most of sorting would satisfy comparing basic values, in some cases a sort operation using custom values is needed. In order to do that, we need to create a class that implements the IComparer interface and set the ListItemSorter property to an object of that class.

Download Sample - Custom Sort Operation in ListView .NET

In the following example we will show how to create a class used for sorting DateTime values. At first initialize the ListView with some data:

private void btnInit_Click(object sender, EventArgs e)

{

int j = 0;

 

// Add two columns

LidorSystems.IntegralUI.Lists.ListViewColumn column = null;

for (j = 1; j <= 2; j++)

{

column = new LidorSystems.IntegralUI.Lists.ListViewColumn();

column.HeaderText = String.Format("Header {0}", j.ToString());

column.FooterText = String.Format("Footer {0}", j.ToString());

column.Width = 100;

 

this.listView1.Columns.Add(column);

}

 

// Create a list of items each containg two subitems

LidorSystems.IntegralUI.Lists.ListViewItem item = null;

LidorSystems.IntegralUI.Lists.ListViewSubItem subItem = null;

 

// A variable used to create random dates

DateTime sampleDate = new DateTime(2009, 1, 1);

Random gen = new Random((int)DateTime.Now.Ticks);

 

for (int i = 1; i <= 50; i++)

{

item = new LidorSystems.IntegralUI.Lists.ListViewItem();

 

for (j = 0; j < this.listView1.Columns.Count; j++)

{

subItem = new LidorSystems.IntegralUI.Lists.ListViewSubItem();

 

// Add DateTime only to the second column

if (j == 1)

{

sampleDate = sampleDate.AddDays(gen.Next(27));

subItem.Text = sampleDate.ToString("dd MMM yyyy");

subItem.SortTag = sampleDate;

}

else

subItem.Text = String.Format("Item {0}{1}", i.ToString(), j.ToString());

 

item.SubItems.Add(subItem);

}

 

this.listView1.Items.Add(item);

}

}

Private Sub btnInit_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnInit.Click

Dim j As Integer = 0

 

' Add two columns

Dim column As LidorSystems.IntegralUI.Lists.ListViewColumn = Nothing

 

For j = 1 To 2

column = New LidorSystems.IntegralUI.Lists.ListViewColumn()

column.HeaderText = [String].Format("Header {0}", j.ToString())

column.FooterText = [String].Format("Footer {0}", j.ToString())

column.Width = 100

 

Me.listView1.Columns.Add(column)

Next

 

' Create a list of items each containg two subitems

Dim item As LidorSystems.IntegralUI.Lists.ListViewItem = Nothing

Dim subItem As LidorSystems.IntegralUI.Lists.ListViewSubItem = Nothing

 

' A variable used to create random dates

Dim sampleDate As New DateTime(2009, 1, 1)

Dim gen As New Random()

 

For i As Integer = 1 To 50

item = New LidorSystems.IntegralUI.Lists.ListViewItem()

 

For j = 0 To Me.listView1.Columns.Count - 1

subItem = New LidorSystems.IntegralUI.Lists.ListViewSubItem()

 

' Add DateTime only to the second column

If j = 1 Then

sampleDate = sampleDate.AddDays(gen.[Next](27))

subItem.Text = sampleDate.ToString("dd MMM yyyy")

subItem.SortTag = sampleDate

Else

subItem.Text = [String].Format("Item {0}{1}", i.ToString(), j.ToString())

End If

 

item.SubItems.Add(subItem)

Next

 

Me.listView1.Items.Add(item)

Next

End Sub

One way to trigger sort operation is by handling the ColumnClick event and change the current sort order:

private void listView1_ColumnClick(object sender, LidorSystems.IntegralUI.ObjectClickEventArgs e)

{

if (e.Object is LidorSystems.IntegralUI.Lists.ListViewColumn)

{

LidorSystems.IntegralUI.Lists.ListViewColumn column = (LidorSystems.IntegralUI.Lists.ListViewColumn)e.Object;

 

// Start the Sort operation only when second column is clicked

if (column.Index == 1)

{

switch (this.listView1.Sorting)

{

case SortOrder.Ascending:

this.listView1.Sorting = SortOrder.Descending;

break;

case SortOrder.Descending:

this.listView1.Sorting = SortOrder.Ascending;

break;

default:

this.listView1.Sorting = SortOrder.Descending;

break;

}

 

// Apply the custom sort operation

this.listView1.ListItemSorter = new DateTimeComparer(this.listView1.Sorting, column.Index);

}

}

}

Private Sub listView1_ColumnClick(ByVal sender As Object, ByVal e As LidorSystems.IntegralUI.ObjectClickEventArgs) Handles listView1.ColumnClick

If TypeOf e.[Object] Is LidorSystems.IntegralUI.Lists.ListViewColumn Then

Dim column As LidorSystems.IntegralUI.Lists.ListViewColumn = DirectCast(e.[Object], LidorSystems.IntegralUI.Lists.ListViewColumn)

 

' Start the Sort operation only when second column is clicked

If column.Index = 1 Then

Select Case Me.listView1.Sorting

Case SortOrder.Ascending

Me.listView1.Sorting = SortOrder.Descending

Exit Select

Case SortOrder.Descending

Me.listView1.Sorting = SortOrder.Ascending

Exit Select

Case Else

Me.listView1.Sorting = SortOrder.Descending

Exit Select

End Select

 

' Apply the custom sort operation

Me.listView1.ListItemSorter = New DateTimeComparer(Me.listView1.Sorting, column.Index)

End If

End If

End Sub

A class which will compare DateTime values is presented in the code below.

public class DateTimeComparer : System.Collections.IComparer

{

private System.Windows.Forms.SortOrder sortType = System.Windows.Forms.SortOrder.Ascending;

private int col = -1;

 

public DateTimeComparer()

{

}

 

public DateTimeComparer(System.Windows.Forms.SortOrder order, int colIndex)

{

sortType = order;

col = colIndex;

}

 

public int Compare(object x, object y)

{

// Switch the objects if the sort order is Descending

if (sortType == System.Windows.Forms.SortOrder.Descending)

{

object temp = x;

x = y;

y = temp;

}

 

object firstDate = null;

object secondDate = null;

 

if (col >= 0)

{

if (col < (x as LidorSystems.IntegralUI.Lists.ListViewItem).SubItems.Count)

firstDate = (x as LidorSystems.IntegralUI.Lists.ListViewItem).SubItems[col].SortTag;

if (col < (y as LidorSystems.IntegralUI.Lists.ListViewItem).SubItems.Count)

secondDate = (y as LidorSystems.IntegralUI.Lists.ListViewItem).SubItems[col].SortTag;

}

 

// Check objects are not empty

if (firstDate != null && secondDate != null)

{

// Compare object values only if they contain DateTime value

if (firstDate.GetType() == typeof(DateTime) && secondDate.GetType() == typeof(DateTime))

return DateTime.Compare((DateTime)firstDate, (DateTime)secondDate);

}

 

return 0;

}

}

Public Class DateTimeComparer

Implements System.Collections.IComparer

Private sortType As System.Windows.Forms.SortOrder = System.Windows.Forms.SortOrder.Ascending

Private col As Integer = -1

 

Public Sub New()

End Sub

 

Public Sub New(ByVal order As System.Windows.Forms.SortOrder, ByVal colIndex As Integer)

sortType = order

col = colIndex

End Sub

 

Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements IComparer.Compare

' Switch the objects if the sort order is Descending

If sortType = System.Windows.Forms.SortOrder.Descending Then

Dim temp As Object = x

x = y

y = temp

End If

 

Dim firstDate As Object = Nothing

Dim secondDate As Object = Nothing

 

If col >= 0 Then

If col < TryCast(x, LidorSystems.IntegralUI.Lists.ListViewItem).SubItems.Count Then

firstDate = TryCast(x, LidorSystems.IntegralUI.Lists.ListViewItem).SubItems(col).SortTag

End If

If col < TryCast(y, LidorSystems.IntegralUI.Lists.ListViewItem).SubItems.Count Then

secondDate = TryCast(y, LidorSystems.IntegralUI.Lists.ListViewItem).SubItems(col).SortTag

End If

End If

 

' Check objects are not empty

If firstDate IsNot Nothing AndAlso secondDate IsNot Nothing Then

' Compare object values only if they contain DateTime value

If firstDate.[GetType]() Is GetType(DateTime) AndAlso secondDate.[GetType]() Is GetType(DateTime) Then

Return DateTime.Compare(DirectCast(firstDate, DateTime), DirectCast(secondDate, DateTime))

End If

End If

 

Return 0

End Function

 

End Class

A sample project in C# and VB showing how to create custom sort operation in ListView is available for download from here: ListView with Custom Sort Operation

Newsletter


Sign-up to our newsletter and you will receive news on upcoming events, latest articles, samples and special offers.
Name: Email: *
*By checking this box, I agree to receive a newsletter from Lidor Systems in accordance with the Privacy Policy. I understand that I can unsubscribe from these communications at any time by clicking on the unsubscribe link in all emails.