none
Sorting items in listview in C#

    Question

  •  


            private int sortColumn = -1;
         
            private void listView1_ColumnClick(object sender, ColumnClickEventArgs e)
            {
                // Determine whether the column is the same as the last column clicked.
                if (e.Column != sortColumn)
                {
                    // Set the sort column to the new column.
                    sortColumn = e.Column;
                    // Set the sort order to ascending by default.
                    listView1.Sorting = SortOrder.Ascending;
                }
                else
                {
                    // Determine what the last sort order was and change it.
                    if (listView1.Sorting == SortOrder.Ascending)
                        listView1.Sorting = SortOrder.Descending;
                    else
                        listView1.Sorting = SortOrder.Ascending;
                }

                // Call the sort method to manually sort.
                listView1.Sort();
                // Set the ListViewItemSorter property to a new ListViewItemComparer
                // object.
                this.listView1.ListViewItemSorter = new ListViewItemComparer(e.Column,listView1.Sorting);
            }
        }

        class ListViewItemComparer : IComparer
        {
             private int col;
                private SortOrder order;
                public ListViewItemComparer()
                {
                    col = 0;
                    order = SortOrder.Ascending;
                }
                public ListViewItemComparer(int column, SortOrder order)
                {
                    col = column;
                    this.order = order;
                }
                public int Compare(object x, object y)
        {
            int returnVal= -1;
            returnVal = String.Compare(((ListViewItem)x).SubItems[col].Text,
                                    ((ListViewItem)y).SubItems[col].Text);
          
            if (order == SortOrder.Descending)
                // Invert the value returned by String.Compare.
                returnVal = 1;
            return returnVal;
                }
        }
    Saturday, December 08, 2007 12:04 AM

Answers

  • I added a regular expression to the Compare procedure to see if the strings are numbers.  If they are I compare them manually other wise I use a string.compare

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;

    namespace ListViewSortCS
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            private int sortColumn = -1;

            private void Form1_Load(object sender, EventArgs e)
            {
                listView1.View = View.Details;
                listView1.Columns.Add("String", 100);
                listView1.Columns.Add("Number", 100);

                for (int x = 0; x < 21; x++)
                {
                    ListViewItem li = new ListViewItem("Item " + x.ToString());
                    li.SubItems.Add(x.ToString());
                    listView1.Items.Add(li);
                }
            }

            private void listView1_ColumnClick(object sender, ColumnClickEventArgs e)
            {
                // Determine whether the column is the same as the last column clicked.
                if (e.Column != sortColumn)
                {
                    // Set the sort column to the new column.
                    sortColumn = e.Column;
                    // Set the sort order to ascending by default.
                    listView1.Sorting = SortOrder.Ascending;
                }
                else
                {
                    // Determine what the last sort order was and change it.
                    if (listView1.Sorting == SortOrder.Ascending)
                        listView1.Sorting = SortOrder.Descending;
                    else
                        listView1.Sorting = SortOrder.Ascending;
                }

                // Call the sort method to manually sort.
                listView1.Sort();
                // Set the ListViewItemSorter property to a new ListViewItemComparer
                // object.
                this.listView1.ListViewItemSorter = new ListViewItemComparer(e.Column, listView1.Sorting);
            }
        }

        class ListViewItemComparer : System.Collections.IComparer
        {
            private int col;
            private SortOrder order;
            public ListViewItemComparer()
            {
                col = 0;
                order = SortOrder.Ascending;
            }
            public ListViewItemComparer(int column, SortOrder order)
            {
                col = column;
                this.order = order;
            }
            public int Compare(object x, object y)
            {
                string s1 = ((ListViewItem)x).SubItems[col].Text;
                string s2 = ((ListViewItem)y).SubItems[col].Text;
                int returnVal = 0;
                System.Text.RegularExpressions.Regex r = new System.Text.RegularExpressions.Regex(@"^\d+$");
                if (!r.IsMatch(s1) && !r.IsMatch(s2))
                {
                    returnVal = String.Compare(s1 , s2);
                }
                else
                {
                    int x1 = int.Parse( s1);
                    int x2 = int.Parse(s2);
                    if(x1 == x2)
                    {
                        returnVal = 0;
                    }
                    else if(x1> x2)
                    {
                        returnVal=1;
                    }
                    else
                    {
                        returnVal=-1;
                    }
                }
                // Determine whether the sort order is descending.
                if (order == SortOrder.Descending)
                    // Invert the value returned by String.Compare.
                    returnVal = returnVal * -1;
                return returnVal;
            }
        }
    }

    Saturday, December 08, 2007 5:49 PM
  • If the radio button is checked call the listview's ColumnClick event passing in the column you want sorted

            private void rbNumber_CheckedChanged(object sender, EventArgs e)
            {
                if (rbNumber.Checked)
                {
                    listView1_ColumnClick(listView1, new ColumnClickEventArgs(1));
                }
            }

            private void rbString_CheckedChanged(object sender, EventArgs e)
            {
                if (rbString.Checked)
                {
                    listView1_ColumnClick(listView1, new ColumnClickEventArgs(0));
                }
            }
    Sunday, December 09, 2007 5:41 PM

All replies

  • I added a regular expression to the Compare procedure to see if the strings are numbers.  If they are I compare them manually other wise I use a string.compare

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;

    namespace ListViewSortCS
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            private int sortColumn = -1;

            private void Form1_Load(object sender, EventArgs e)
            {
                listView1.View = View.Details;
                listView1.Columns.Add("String", 100);
                listView1.Columns.Add("Number", 100);

                for (int x = 0; x < 21; x++)
                {
                    ListViewItem li = new ListViewItem("Item " + x.ToString());
                    li.SubItems.Add(x.ToString());
                    listView1.Items.Add(li);
                }
            }

            private void listView1_ColumnClick(object sender, ColumnClickEventArgs e)
            {
                // Determine whether the column is the same as the last column clicked.
                if (e.Column != sortColumn)
                {
                    // Set the sort column to the new column.
                    sortColumn = e.Column;
                    // Set the sort order to ascending by default.
                    listView1.Sorting = SortOrder.Ascending;
                }
                else
                {
                    // Determine what the last sort order was and change it.
                    if (listView1.Sorting == SortOrder.Ascending)
                        listView1.Sorting = SortOrder.Descending;
                    else
                        listView1.Sorting = SortOrder.Ascending;
                }

                // Call the sort method to manually sort.
                listView1.Sort();
                // Set the ListViewItemSorter property to a new ListViewItemComparer
                // object.
                this.listView1.ListViewItemSorter = new ListViewItemComparer(e.Column, listView1.Sorting);
            }
        }

        class ListViewItemComparer : System.Collections.IComparer
        {
            private int col;
            private SortOrder order;
            public ListViewItemComparer()
            {
                col = 0;
                order = SortOrder.Ascending;
            }
            public ListViewItemComparer(int column, SortOrder order)
            {
                col = column;
                this.order = order;
            }
            public int Compare(object x, object y)
            {
                string s1 = ((ListViewItem)x).SubItems[col].Text;
                string s2 = ((ListViewItem)y).SubItems[col].Text;
                int returnVal = 0;
                System.Text.RegularExpressions.Regex r = new System.Text.RegularExpressions.Regex(@"^\d+$");
                if (!r.IsMatch(s1) && !r.IsMatch(s2))
                {
                    returnVal = String.Compare(s1 , s2);
                }
                else
                {
                    int x1 = int.Parse( s1);
                    int x2 = int.Parse(s2);
                    if(x1 == x2)
                    {
                        returnVal = 0;
                    }
                    else if(x1> x2)
                    {
                        returnVal=1;
                    }
                    else
                    {
                        returnVal=-1;
                    }
                }
                // Determine whether the sort order is descending.
                if (order == SortOrder.Descending)
                    // Invert the value returned by String.Compare.
                    returnVal = returnVal * -1;
                return returnVal;
            }
        }
    }

    Saturday, December 08, 2007 5:49 PM
  • excellent  thank you very much its working is it possible to call the this column click event in the following event

     private void radioButton1_CheckedChanged(object sender, EventArgs e)
            {
               
             
            }
    Saturday, December 08, 2007 8:08 PM
  • If the radio button is checked call the listview's ColumnClick event passing in the column you want sorted

            private void rbNumber_CheckedChanged(object sender, EventArgs e)
            {
                if (rbNumber.Checked)
                {
                    listView1_ColumnClick(listView1, new ColumnClickEventArgs(1));
                }
            }

            private void rbString_CheckedChanged(object sender, EventArgs e)
            {
                if (rbString.Checked)
                {
                    listView1_ColumnClick(listView1, new ColumnClickEventArgs(0));
                }
            }
    Sunday, December 09, 2007 5:41 PM
  • thank you very much
    Sunday, December 09, 2007 11:31 PM
  • Hi Ken,

    I went step-by-step with sorting listView, but in my code is doing nothing... I dont know if I miss sth.. my code contains other algorithms, but it shouldnt affect... Sad
    It writes no error, just it is not working and have no idea where can be a mistake Sad

    Thanks a lot...
    Tuesday, April 29, 2008 5:41 PM
  • It is ok, I just find a mistake Smile but anyway thanks for this forum Smile
    Tuesday, April 29, 2008 5:57 PM