ListView CodeSample - ListViewItemSorter that sorts various types of data including control type columns

From Visual WebGui Wiki

Jump to: navigation, search


Contents

Overview

This sample demonstrates a way to implement a custom ListView sorting class that can sort various types of data contained within the ListView. What type of data it sorts and how it is sorted, is determined by the way you customize the class for your needs. The sample in this article implements an IComparer class that can handle sorting on columns of type Text, Number and Control. It also demonstrates how you can handle the case when the Control within the ListViewSubItem is a Panel, by sorting on the first Control of that Panel.

It should also be noted that the way the custom sorting class is implemented, it will handle sorting on multiple columns correctly.

How to use the sorter class

The way to use this custom IComparer class is demonstrated in the code that follows, in the form section. In short, the only thing you have to do is to assign an instance of the class to ListView.ListViewItemSorter, and that's it. No need to

VB.NET Code

Required Imports

Imports Gizmox.WebGUI.Forms
Imports Gizmox.WebGUI.Common
Imports Gizmox.WebGUI.Forms.ListViewItem

The Form

Public Class SortDemo
    Inherits Form
 
    Private ListView1 As ListView
 
    Private Sub BuildColumns()
        Dim Ch As ColumnHeader = New ColumnHeader
        Ch.Text = "Text"
        Ch.Type = ListViewColumnType.Text
        Ch.Width = 100
        ListView1.Columns.Add(Ch)
 
        Ch = New ColumnHeader
        Ch.Text = "Number"
        Ch.Type = ListViewColumnType.Number
        Ch.Width = 100
        ListView1.Columns.Add(Ch)
 
        Ch = New ColumnHeader
        Ch.Text = "LinkLabel"
        Ch.Type = ListViewColumnType.Control
        Ch.Width = 100
        ListView1.Columns.Add(Ch)
 
        Ch = New ColumnHeader
        Ch.Text = "Panel"
        Ch.Type = ListViewColumnType.Control
        Ch.Width = 100
        ListView1.Columns.Add(Ch)
    End Sub
 
    Private Sub SortDemo_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ListView1 = New ListView()
        ListView1.Dock = DockStyle.Fill
        Me.Controls.Add(ListView1)
        BuildColumns()
 
        ' Load data
        For i As Integer = 1 To 100
            Dim LI As ListViewItem = New ListViewItem()
            LI.SubItems.Add(i.ToString())
            LI.SubItems.Add(i)
            LI.SubItems.Add(New LinkLabel("LinkLabel " + i.ToString(), "http://www.visualwebgui.com"))
            Dim P As Panel = New Panel()
            Dim T As TextBox = New TextBox()
            T.Dock = DockStyle.Fill
            P.Controls.Add(T)
            T.Text = "TextBox " + i.ToString()
            LI.SubItems.Add(P)
            ListView1.Items.Add(LI)
        Next
        ListView1.ListViewItemSorter = New MyLISorter(Me.ListView1)
    End Sub
 
End Class

The sorter class

Public Class MyLISorter
    Implements System.Collections.IComparer
 
    Private mobjListView As ListView
 
    Public Sub New(ByVal LI As ListView)
        mobjListView = LI
    End Sub
 
    Private Function GetSortingColumns() As ICollection
        Dim objSortData As ColumnHeaderSortingData = New ColumnHeaderSortingData(mobjListView)
        Return objSortData.SortingColumns
    End Function
 
    Public Function GetControlSortString(ByVal C As Control) As String
        ' Customize logic at will. Return string suitable for sorting.
        If C Is Nothing Then
            Return ""
        ElseIf C.GetType() Is GetType(Panel) Then
            Dim P As Panel = CType(C, Panel)
            If P.Controls.Count = 0 Then
                ' If no controls on panel, empty string
                Return ""
            Else
                ' Sort by the first control on the panel
                Return GetControlSortString(P.Controls(0))
            End If
        Else
            Return C.Text
        End If
    End Function
    Public Function Compare(ByVal objObjectA As Object, ByVal objObjectB As Object) As Integer Implements System.Collections.IComparer.Compare
        ' Get list viewitems
        Dim objItemA As ListViewItem = TryCast(objObjectA, ListViewItem)
        Dim objItemB As ListViewItem = TryCast(objObjectB, ListViewItem)
 
        Dim objSortingColumns As ICollection = Me.GetSortingColumns
 
        ' Check valid items
        If objItemA IsNot Nothing AndAlso objItemB IsNot Nothing Then
            ' Check that there are columns
            If objSortingColumns.Count = 0 Then
                Return 0
            Else
                ' Loop all sorting columns
                For Each objColumn As ColumnHeader In objSortingColumns
                    ' Get sorting direction
                    Dim intDirection As Integer = If((objColumn.SortOrder = SortOrder.Ascending), 1, -1)
 
                    ' The comparison result
                    Dim intResult As Integer = 0
                    If objColumn.Type = ListViewColumnType.Number Then
                        intResult = CType(objItemA.SubItems(objColumn.Index).Text, Integer).CompareTo(CType(objItemB.SubItems(objColumn.Index).Text, Integer))
                    ElseIf objColumn.Type = ListViewColumnType.Control Then
                        ' Compare controls
                        Dim objControlA, objControlB As ListViewSubControlItem
                        objControlA = objItemA.SubItems(objColumn.Index)
                        objControlB = objItemB.SubItems(objColumn.Index)
                        intResult = GetControlSortString(objControlA.Control).CompareTo(GetControlSortString(objControlB.Control))
                    Else
                        ' Compare Text property by default
                        intResult = objItemA.SubItems(objColumn.Index).Text.CompareTo(objItemB.SubItems(objColumn.Index).Text)
                    End If
                    If intResult <> 0 Then
                        Return intResult * intDirection
                    End If
                Next
                Return 0
            End If
        Else
            Return 0
        End If
    End Function
 
End Class

C# Code

Required using

using System.Collections;
using Gizmox.WebGUI.Common;
using Gizmox.WebGUI.Forms;

The Form

public partial class SortDemo : Form
    {
        public Form2()
        {
            InitializeComponent();
            this.Load += this.SortDemo_Load;
        }
 
        private ListView ListView1;
        private void BuildColumns()
        {
            ColumnHeader Ch = new ColumnHeader();
            Ch.Text = "Text";
            Ch.Type = ListViewColumnType.Text;
            Ch.Width = 100;
            ListView1.Columns.Add(Ch);
 
            Ch = new ColumnHeader();
            Ch.Text = "Number";
            Ch.Type = ListViewColumnType.Number;
            Ch.Width = 100;
            ListView1.Columns.Add(Ch);
 
            Ch = new ColumnHeader();
            Ch.Text = "LinkLabel";
            Ch.Type = ListViewColumnType.Control;
            Ch.Width = 100;
            ListView1.Columns.Add(Ch);
 
            Ch = new ColumnHeader();
            Ch.Text = "Panel";
            Ch.Type = ListViewColumnType.Control;
            Ch.Width = 100;
            ListView1.Columns.Add(Ch);
        }
        private void SortDemo_Load(System.Object sender, System.EventArgs e)
        {
            ListView1 = new ListView();
            ListView1.Dock = DockStyle.Fill;
            this.Controls.Add(ListView1);
            BuildColumns();
 
            // Load data
            for (int i = 1; i <= 100; i++)
            {
                ListViewItem LI = new ListViewItem();
                LI.SubItems.Add(i.ToString());
                LI.SubItems.Add(i.ToString());
                LI.SubItems.Add(new LinkLabel("LinkLabel " + i.ToString(), "http://www.visualwebgui.com"));
                Panel P = new Panel();
                TextBox T = new TextBox();
                T.Dock = DockStyle.Fill;
                P.Controls.Add(T);
                T.Text = "TextBox " + i.ToString();
                LI.SubItems.Add(P);
                ListView1.Items.Add(LI);
            }
            ListView1.ListViewItemSorter = new MyLISorter(this.ListView1);
        }
 
    }

The sorter class

public class MyLISorter : System.Collections.IComparer
{
   private ListView mobjListView;
   public MyLISorter(ListView LI)
   {
      mobjListView = LI;
   }
 
   private ICollection GetSortingColumns()
   {
      ColumnHeaderSortingData objSortData = new ColumnHeaderSortingData(mobjListView);
      return (ICollection)objSortData.SortingColumns;
   }
 
   public string GetControlSortString(Control C)
   {
      // Customize logic at will. Return string suitable for sorting.
      if (C == null) {
         return "";
      } else if (object.ReferenceEquals(C.GetType(), typeof(Panel))) {
         Panel P = (Panel)C;
         if (P.Controls.Count == 0) {
            // If no controls on panel, empty string
            return "";
         } else {
            // Sort by the first control on the panel
            return GetControlSortString(P.Controls[0]);
         }
      } else {
         return C.Text;
      }
   }
 
   public int Compare(object objObjectA, object objObjectB)
   {
      // Get list viewitems
      ListViewItem objItemA = objObjectA as ListViewItem;
      ListViewItem objItemB = objObjectB as ListViewItem;
 
      ICollection objSortingColumns = this.GetSortingColumns();
 
      // Check valid items
      if (objItemA != null && objItemB != null) {
         // Check that there are columns
         if (objSortingColumns.Count == 0) {
            return 0;
         } else {
            // Loop all sorting columns
            foreach (ColumnHeader objColumn in objSortingColumns) {
               // Get sorting direction
               int intDirection = (objColumn.SortOrder == SortOrder.Ascending) ? 1 : -1;
 
               // The comparison result
               int intResult = 0;
               if (objColumn.Type == ListViewColumnType.Number) {
                  intResult = Convert.ToInt32(objItemA.SubItems[objColumn.Index].Text).CompareTo(Convert.ToInt32(objItemB.SubItems[objColumn.Index].Text));
               } else if (objColumn.Type == ListViewColumnType.Control) {
                  // Compare controls
                  ListViewItem.ListViewSubControlItem objControlA;
                  ListViewItem.ListViewSubControlItem objControlB;
                  objControlA = (ListViewItem.ListViewSubControlItem)objItemA.SubItems[objColumn.Index];
                  objControlB = (ListViewItem.ListViewSubControlItem)objItemB.SubItems[objColumn.Index];
                  intResult = GetControlSortString(objControlA.Control).CompareTo(GetControlSortString(objControlB.Control));
               } else {
                  // Compare Text property by default
                  intResult = objItemA.SubItems[objColumn.Index].Text.CompareTo(objItemB.SubItems[objColumn.Index].Text);
               }
               if (intResult != 0) {
                  return intResult * intDirection;
               }
            }
            return 0;
         }
      } else {
         return 0;
      }
   }
}
Personal tools