how do I sort Integers in a listview

前端 未结 7 1685
天命终不由人
天命终不由人 2020-12-16 06:04

How do I sort columns of integers in a ListView

c#, .net 2.0, Winform

System.Windows.Forms.ListView

相关标签:
7条回答
  • 2020-12-16 06:10
    class ListViewAutoSorter : System.Collections.IComparer
    {
        private int Column = 0;
        private System.Windows.Forms.SortOrder Order = SortOrder.Ascending;
    
        public ListViewAutoSorter(int Column, SortOrder Order)
        {
            this.Column = Column;
            this.Order = Order;
        }
    
        public int Compare(object x, object y) // IComparer Member
        {
            if (!(x is ListViewItem))
                return (0);
            if (!(y is ListViewItem))
                return (0);
    
            var l1 = (ListViewItem)x;
            var l2 = (ListViewItem)y;
    
            var value1 = 0.0;
            var value2 = 0.0;
    
            if (Double.TryParse(l1.SubItems[Column].Text, out value1) && 
                Double.TryParse(l2.SubItems[Column].Text, out value2))
            {
                if (Order == SortOrder.Ascending)
                {
                    return value1.CompareTo(value2);
                }
                else
                {
                    return value2.CompareTo(value1);
                }
            }
            else
            {
                var str1 = l1.SubItems[Column].Text;
                var str2 = l2.SubItems[Column].Text;
    
                if (Order == SortOrder.Ascending)
                {
                    return str1.CompareTo(str2);
                }
                else
                {
                    return str2.CompareTo(str1);
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-16 06:15

    This is how I accomplished being able to sort on multiple columns, and being able to sort each column as a number, or as text.

    First use this class:

    class Sorter : System.Collections.IComparer
    {
        public int Column = 0;
        public System.Windows.Forms.SortOrder Order = SortOrder.Ascending;
        public int Compare(object x, object y) // IComparer Member
        {
            if (!(x is ListViewItem))
                return (0);
            if (!(y is ListViewItem))
                return (0);
    
            ListViewItem l1 = (ListViewItem)x;
            ListViewItem l2 = (ListViewItem)y;
    
            if (l1.ListView.Columns[Column].Tag == null)
            {
                l1.ListView.Columns[Column].Tag = "Text";
            }
    
            if (l1.ListView.Columns[Column].Tag.ToString() == "Numeric")
            {
                float fl1 = float.Parse(l1.SubItems[Column].Text);
                float fl2 = float.Parse(l2.SubItems[Column].Text);
    
                if (Order == SortOrder.Ascending)
                {
                    return fl1.CompareTo(fl2);
                }
                else
                {
                    return fl2.CompareTo(fl1);
                }
            }
            else
            {
                string str1 = l1.SubItems[Column].Text;
                string str2 = l2.SubItems[Column].Text;
    
                if (Order == SortOrder.Ascending)
                {
                    return str1.CompareTo(str2);
                }
                else
                {
                    return str2.CompareTo(str1);
                }
            }
        }
    }
    

    In your form's constructor, set the sorter like this:

    lvSeries.ListViewItemSorter = new Sorter();
    

    Then handle the ColumnClick even of your listview control like this:

    private void lvSeries_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            Sorter s = (Sorter)lvSeries.ListViewItemSorter;
            s.Column = e.Column;
    
            if (s.Order == System.Windows.Forms.SortOrder.Ascending)
            {
                s.Order = System.Windows.Forms.SortOrder.Descending;
            }
            else
            {
                s.Order = System.Windows.Forms.SortOrder.Ascending;
            }
            lvSeries.Sort();
        }
    

    This is all dependent on the Tag property of each column either being set to "Numeric" or not, so the sorter knows how to sort.

    In the above example I cast the values as floats when numeric, you may want to change that to int.

    0 讨论(0)
  • 2020-12-16 06:16
    Public Class Form1
    
    Private Sub btnSortListView_Click(sender As Object, e As EventArgs) Handles btnSortListView.Click
            If btnSortListView.Text = "Sort Ascending" Then
    
                ListViewGar.ListViewItemSorter = New IntegerComparer(1)
                ListViewGar.Sort()
    
                btnSortListView.Text = "Not Sort"
    
            Else
                ListViewGar.ListViewItemSorter = New IntegerComparer(0)
                btnSortListView.Text = "Sort Ascending"
            End If
    
        End Sub
    End Class
    
     Public Class IntegerComparer
        Implements System.Collections.IComparer
    
        Private _colIndex As Integer
    
        Public Sub New(ByVal colIndex As Integer)
            MyBase.New
            Me._colIndex = colIndex
        End Sub
    
        'Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer
        '    Dim nx As Integer = Integer.Parse(CType(x, ListViewItem).SubItems(Me._colIndex).Text)
        '    Dim ny As Integer = Integer.Parse(CType(y, ListViewItem).SubItems(Me._colIndex).Text)
        '    Return nx.CompareTo(ny)
        'End Function
    
        Private Function IComparer_Compare(x As Object, y As Object) As Integer Implements IComparer.Compare
            Dim nx As Integer = Integer.Parse(CType(x, ListViewItem).SubItems(Me._colIndex).Text)
            Dim ny As Integer = Integer.Parse(CType(y,ListViewItem).SubItems(Me._colIndex).Text)
    
            Dim colIndPlus As Integer = Me._colIndex
            Do While nx.CompareTo(ny) = 0
                colIndPlus = colIndPlus + 1
                nx = Integer.Parse(CType(x, ListViewItem).SubItems(colIndPlus).Text)
                ny = Integer.Parse(CType(y, ListViewItem).SubItems(colIndPlus).Text)
            Loop
    
            Return nx.CompareTo(ny)
    
        End Function
    End Class
    

    image before and after sort

    0 讨论(0)
  • 2020-12-16 06:21

    I'd do it in the data source (model) instead of the view. Sort it there and it should update it in the view through databinding.

    0 讨论(0)
  • 2020-12-16 06:22

    You will need to create a class that implements the IComparer interface (the non-generic one). In that class you read the Text property from the correct sub-item, convert it to int, and do the comparison:

    public class IntegerComparer : IComparer
    {
        private int _colIndex;
        public IntegerComparer(int colIndex)
        {
            _colIndex = colIndex;
        }
        public int Compare(object x, object y)
        {
            int nx = int.Parse((x as ListViewItem).SubItems[_colIndex].Text);
            int ny = int.Parse((y as ListViewItem).SubItems[_colIndex].Text);
            return nx.CompareTo(ny);
        }
    }
    

    Then you assign such a comparer to the ListViewItemSorter property and invoke the sort method of the ListView control:

    // create a comparer for column index 1 and assign it to the control, and sort
    myListView.ListViewItemSorter = new IntegerComparer(1);
    myListView.Sort();
    
    0 讨论(0)
  • 2020-12-16 06:27

    If you are getting started with a ListView, your life will be much much easier if you use an ObjectListView instead. ObjectListView is an open source wrapper around .NET WinForms ListView, and it solves all these annoying little problems that normally make working with a ListView so frustrating. For example, it automatically sorts ints so that '100' comes after '3' (DateTimes, bools, and everything else sorts correctly too).

    Seriously, you will never want to go back to a plain ListView after using an ObjectListView.

    Yes, I am the author -- but that doesn't mean I'm biased... OK, well maybe it does :) Look here for some other people's opinions.

    0 讨论(0)
提交回复
热议问题