Search code examples
c#.netwinformsc#-4.0listviewitem

How to sort a list view column having $ sign like amount?


I am facing some problem in sorting. I have the following code from msd document it works for all field, but not for amount fields that start with character like $ for example

     amount
      $1900
      $4444 
      $39
      $0

This code does not sort that column so what changes should i make so that it also sorts the amount having $ sign at start.

This is the code:

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);
    // Determine whether the sort order is descending.
    if(order == SortOrder.Descending)
        // Invert the value returned by String.Compare.
        returnVal *= -1
    return returnVal;
 }
}

and I am calling that code in listview column click event as

    private void lvwUsers_ColumnClick(Object eventSender, ColumnClickEventArgs eventArgs)
    {


        if (lvwUsers.Sorting == SortOrder.Ascending)
            lvwUsers.Sorting = SortOrder.Descending;
        else
            lvwUsers.Sorting = SortOrder.Ascending;

        lvwUsers.Sort();

        this.lvwUsers.ListViewItemSorter = new ListViewItemComparer(eventArgs.Column,
                                                          lvwUsers.Sorting);

      }

It works fine but not for amount having $ sign with them

So how to sort listview having amount column with $ sign?


Solution

  • You already have a comparer. Why not just modify it to sort the way you want? Use Decimal.Parse to convert the strings to decimal values, then compare those instead. No need to modify your list data. It also self-adapts to different cultures.

    If the data can contain something other than currency values, you may want to make this code a bit more resilient to handle whatever types of values you get.

        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;
                decimal value1;
                Decimal.TryParse(((ListViewItem)x).SubItems[col].Text,
                                 System.Globalization.NumberStyles.Currency,
                                 System.Globalization.CultureInfo.CurrentUICulture, 
                                 out value1);
                decimal value2;
                Decimal.TryParse(((ListViewItem)y).SubItems[col].Text,
                                 System.Globalization.NumberStyles.Currency, 
                                 System.Globalization.CultureInfo.CurrentUICulture, 
                                 out value2);
                returnVal = Decimal.Compare(value1, value2);
                // Determine whether the sort order is descending.
                if (order == SortOrder.Descending)
                    // Invert the value returned by String.Compare.
                    returnVal *= -1;
                return returnVal;
            }
        }