如何在ListView中对整数进行排序

7

如何在ListView中对整数列进行排序

c#,.net 2.0,Winform

System.Windows.Forms.ListView


1
ASP.NET?Windows Forms? - Dan Diplo
我编辑了我的答案,包括一个完整的例子,可以对文本和数字进行排序。 - Neil N
7个回答

21

这是我完成对多个列进行排序以及对每个列按数字或文本排序的方法:

首先使用以下类:

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);
            }
        }
    }
}

在你的表单构造函数中,像这样设置排序器:

lvSeries.ListViewItemSorter = new Sorter();

然后像这样处理您的列表视图控件的ColumnClick事件:

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();
    }

这完全取决于每列的标签属性是否设置为“Numeric”,以便排序器知道如何排序。

在上面的示例中,当数字时,我将值强制转换为浮点数,您可能希望将其更改为整数。


1
@Neil:默认情况下,它将它们作为文本进行排序。例如,100排在3之前。但是,您可以使用自定义的ListViewItemSorter正确地对int进行排序。 - Josip Medved
我按照http://support.microsoft.com/kb/319401上的示例操作,但整数仍无法正确排序。关于文本,如何设置默认列进行排序?在第一列上排序很好,但我找不到要设置的列属性。 - Brad
1
太好了!我刚刚使用了许多显示网格列名的页面,例如 **'ID'**。 因此,我将 if (l1.ListView.Columns[Column].Tag.ToString() == "Numeric") 更改为 if (l1.ListView.Columns[Column]..Text.ToUpper.IndexOf("ID") > -1。 这个方法可行。感谢分享! - HATCHA

5
如果你刚开始使用ListView,那么如果你使用ObjectListView,你的生活将会变得更加轻松。ObjectListView是一个.NET WinForms ListView的开源包装器,它解决了所有这些烦人的小问题,这些问题通常会让使用ListView变得非常令人沮丧。例如,它自动对int进行排序,以便'100'在'3'之后(DateTimes、bools和其他所有内容也可以正确排序)。
说真的,在使用ObjectListView之后,你永远不想回到普通的ListView了。
是的,我是作者——但这并不意味着我有偏见……好吧,也许有 :) 点击这里查看其他人的意见。

4

您需要创建一个实现IComparer接口(非泛型版本)的类。在该类中,您需要读取正确子项的Text属性,将其转换为整数,并进行比较:

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);
    }
}

然后您将这样的比较器分配给ListViewItemSorter属性,并调用ListView控件的sort方法:
// create a comparer for column index 1 and assign it to the control, and sort
myListView.ListViewItemSorter = new IntegerComparer(1);
myListView.Sort();

一些列是数值型,而其他列是文本类型...我排序前应该先测试一下是否为数值型吗? - Brad
1
我曾经编写了一个ListViewItem比较器,它在Compare方法中检查每个元素对,但这变得相当缓慢。你最好拥有单独的比较器,并根据正在排序的列选择使用哪个,或者创建一个比较器类,在构造函数中传递一个值以指示基于数字、日期或文本进行排序,然后根据该值在Compare方法中切换(这是我在那种情况下选择的解决方案)。 - Fredrik Mörk
不错的想法。但是我在我的listview比较类中创建了一个名为“sortType”的私有变量。 - Chris

0

我使用了Neil-N的类,但将if语句更改为测试Type属性而不是Tag属性。对于每个具有整数值的列,我将其设置为Type Number(而不是Text)。排序效果很好。

if (l1.ListView.Columns[Column].Type.ToString() == "Number")

我不确定你是否漏掉了什么内容,但是ColumnHeader没有Type属性。 - Nick

0
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

排序前后的图片


这个问题是关于C#的...但大多数人可能都能翻译。 - Chris Catignani

0
我会在数据源(模型)中完成它,而不是在视图中。在那里进行排序,通过数据绑定它应该会在视图中更新。

你的意思是在每次点击列时,对数据源(在这个例子中是datatable)进行排序,然后重新加载listview吗? - Brad
不,每次重新加载是不好的做法。谷歌搜索“ListViewItemSorter”,它会向您展示如何按每列排序。 - Neil N
糟糕...我不知道这是用于Windows窗体的。我只是假设是WPF。 - Jimmy Chandra

0
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);
            }
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接