ListView CodeSample - ListViewItemSorter that sorts various types of data including control type columns
From Visual WebGui Wiki
| This article will have a few sections added to it soon, based on the following article type skeleton: NewCodeSampleTemplate |
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; } } }
