【问题标题】:Sorting A ListView By Column按列对 ListView 进行排序
【发布时间】:2009-10-10 16:00:44
【问题描述】:

目前我在列表视图上使用自定义排序器,每次单击第一列时都可以对列表视图进行排序,但不会按其他列排序。

SortStyle:用于确定是升序还是降序的变量。

if (e.Column == 0)
{
    if (SortStyle == 0)
    {
        List.ListViewItemSorter = customSortDsc;
        SortStyle = 1;
    }
    else
    {
        List.ListViewItemSorter = customSortAsc;
        SortStyle = 0;
    }
}

这在对第一列进行排序时效果很好,但如果您要对任何其他列进行排序,它只会按第一列排序。有没有办法按点击的列排序?

【问题讨论】:

  • 迈克,如果您查看下面的示例,我认为您正在寻找 ColumnClickEventArgs.Column 值。它会告诉你点击了哪个列标题。

标签: c# sorting listview


【解决方案1】:

忘记您的自定义分拣机。使用下一页的代码重新开始。它将向您展示如何定义一个从 IComparer 接口继承的类。每一行都被注释掉了,所以你可以实际看到发生了什么。唯一潜在的复杂性是如何从 Listview 控件中检索 Listview 项。把这些平方和所有你需要做的就是复制和粘贴 IComparer 接口类和 columnClick 方法。

http://support.microsoft.com/kb/319401

【讨论】:

  • 非常有用的链接。似乎是最简单的解决方案。谢谢红眼。
  • 或者更好的是,使用上面链接的代码创建您自己的 SortableListView,然后您需要更改的只是初始化列表的一行。
  • 由于事件接收器中的代码是非常标准的行为,我在 ListViewColumnSorter 类中添加了一个 ReverseSortOrderAndSort(int column, ListView lv) 方法因此事件接收器中的代码变为: private void listView1_ColumnClick(object sender, ColumnClickEventArgs e) { listViewColumnSorter.ReverseSortOrderAndSort(e.Column, (ListView)sender); }
  • 一个很好的无痛解决方案,完全跳过了 GNU 头痛 ObjectListView 附带
【解决方案2】:

如果您从 ListView 开始,请帮自己一个大忙,改用 ObjectListView。 ObjectListView 是一个围绕 .NET WinForms ListView 的开源包装器,它使 ListView 更易于使用并为您解决了许多常见问题。按列点击排序是它自动为您处理的众多事情之一。

说真的,你永远不会后悔使用 ObjectListView 而不是普通的 ListView。

【讨论】:

  • 我以前使用过 ObjectListView 并且喜欢它。您必须注意的一件事是它是 GPL,因此您可能必须发布您的源代码。
  • 可能必须?有人知道我们是否可以使用 GPL 吗?我真正想知道的是:我是否可以合法地将它用于已出售而非开源的商业软件中? (在欧洲和美国)
  • 如果你想在一个闭源应用程序中使用它,你可以购买一个(便宜的)许可证:objectlistview.sourceforge.net/cs/…
  • x64下有些东西坏了(比如分组)
  • ObjectListView 在 x64(这是我的日常工作环境)下可以正常工作,包括分组。如果您遇到问题,何不在讨论组sourceforge.net/p/objectlistview/discussion/812922 上发布消息?
【解决方案3】:

我使用列名进行排序,以设置任何可能需要根据存储在列中的数据类型处理的排序细节,或者如果该列已经排序(asc/desc)。这是来自我的 ColumnClick 事件处理程序的 sn-p。

private void listView_ColumnClick(object sender, ColumnClickEventArgs e)
    {
        ListViewItemComparer sorter = GetListViewSorter(e.Column);

        listView.ListViewItemSorter = sorter;
        listView.Sort();
    }

    private ListViewItemComparer GetListViewSorter(int columnIndex)
    {
        ListViewItemComparer sorter = (ListViewItemComparer)listView.ListViewItemSorter;
        if (sorter == null)
        {
            sorter = new ListViewItemComparer();
        }

        sorter.ColumnIndex = columnIndex;

        string columnName = packagedEstimateListView.Columns[columnIndex].Name;
        switch (columnName)
        {
            case ApplicationModel.DisplayColumns.DateCreated:
            case ApplicationModel.DisplayColumns.DateUpdated:
                sorter.ColumnType = ColumnDataType.DateTime;
                break;
            case ApplicationModel.DisplayColumns.NetTotal:
            case ApplicationModel.DisplayColumns.GrossTotal:
                sorter.ColumnType = ColumnDataType.Decimal;
                break;
            default:
                sorter.ColumnType = ColumnDataType.String;
                break;
        }

        if (sorter.SortDirection == SortOrder.Ascending)
        {
            sorter.SortDirection = SortOrder.Descending;
        }
        else
        {
            sorter.SortDirection = SortOrder.Ascending;
        }

        return sorter;
    }

下面是我的 ListViewItemComparer

public class ListViewItemComparer : IComparer
{
    private int _columnIndex;
    public int ColumnIndex
    {
        get
        {
            return _columnIndex;
        }
        set
        {
            _columnIndex = value;
        }
    }

    private SortOrder _sortDirection;
    public SortOrder SortDirection
    {
        get
        {
            return _sortDirection;
        }
        set
        {
            _sortDirection = value;
        }
    }

    private ColumnDataType _columnType;
    public ColumnDataType ColumnType
    {
        get
        {
            return _columnType;
        }
        set
        {
            _columnType = value;
        }
    }


    public ListViewItemComparer()
    {
        _sortDirection = SortOrder.None;
    }

    public int Compare(object x, object y)
    {
        ListViewItem lviX = x as ListViewItem;
        ListViewItem lviY = y as ListViewItem;

        int result;

        if (lviX == null && lviY == null)
        {
            result = 0;
        }
        else if (lviX == null)
        {
            result = -1;
        }

        else if (lviY == null)
        {
            result = 1;
        }

        switch (ColumnType)
        {
            case ColumnDataType.DateTime:
                DateTime xDt = DataParseUtility.ParseDate(lviX.SubItems[ColumnIndex].Text);
                DateTime yDt = DataParseUtility.ParseDate(lviY.SubItems[ColumnIndex].Text);
                result = DateTime.Compare(xDt, yDt);
                break;

            case ColumnDataType.Decimal:
                Decimal xD = DataParseUtility.ParseDecimal(lviX.SubItems[ColumnIndex].Text.Replace("$", string.Empty).Replace(",", string.Empty));
                Decimal yD = DataParseUtility.ParseDecimal(lviY.SubItems[ColumnIndex].Text.Replace("$", string.Empty).Replace(",", string.Empty));
                result = Decimal.Compare(xD, yD);
                break;
            case ColumnDataType.Short:
                short xShort = DataParseUtility.ParseShort(lviX.SubItems[ColumnIndex].Text);
                short yShort = DataParseUtility.ParseShort(lviY.SubItems[ColumnIndex].Text);
                result = xShort.CompareTo(yShort);
                break;
            case ColumnDataType.Int:
                int xInt = DataParseUtility.ParseInt(lviX.SubItems[ColumnIndex].Text);
                int yInt = DataParseUtility.ParseInt(lviY.SubItems[ColumnIndex].Text);
                return xInt.CompareTo(yInt);
                break;
            case ColumnDataType.Long:
                long xLong = DataParseUtility.ParseLong(lviX.SubItems[ColumnIndex].Text);
                long yLong = DataParseUtility.ParseLong(lviY.SubItems[ColumnIndex].Text);
                return xLong.CompareTo(yLong);
                break;
            default:

                result = string.Compare(
                    lviX.SubItems[ColumnIndex].Text,
                    lviY.SubItems[ColumnIndex].Text,
                    false);

                break;
        }

        if (SortDirection == SortOrder.Descending)
        {
            return -result;
        }
        else
        {
            return result;
        }
    }
}

【讨论】:

  • 这个页面提供了类似的解决方案-> java2s.com/Tutorial/CSharp/0460__GUI-Windows-Forms/…
  • 根据我上面提供的链接创建 ListViewitemComparer 时,您需要添加此代码以进行升序/降序排序: string itemXText = itemX.SubItems[Column].Text;字符串 itemYText = itemY.SubItems[Column].Text; //排序 if (itemX.ListView.Sorting == SortOrder.Ascending) { return String.Compare(itemXText, itemYText); } else { return String.Compare(itemYText, itemXText); }
  • @will-p 你能展示一下 ListViewItemComparer 的样子吗?
  • @slayernoah - 请参阅上面的 ListItemViewComparer 更新
  • 您在哪里(以及如何)定义自己的类型ColumnDataType
【解决方案4】:

对文章 here 进行了细微更改,以适应 ListView 中字符串和数值的排序。

Form1.cs 包含

using System;
using System.Windows.Forms;

namespace ListView
{
    public partial class Form1 : Form
    {
        Random rnd = new Random();
        private ListViewColumnSorter lvwColumnSorter;

        public Form1()
        {
            InitializeComponent();
            // Create an instance of a ListView column sorter and assign it to the ListView control.
            lvwColumnSorter = new ListViewColumnSorter();
            this.listView1.ListViewItemSorter = lvwColumnSorter;

            InitListView();
        }

        private void InitListView()
        {
            listView1.View = View.Details;
            listView1.GridLines = true;
            listView1.FullRowSelect = true;

            //Add column header
            listView1.Columns.Add("Name", 100);
            listView1.Columns.Add("Price", 70);
            listView1.Columns.Add("Trend", 70);

            for (int i = 0; i < 10; i++)
            {
                listView1.Items.Add(AddToList("Name" + i.ToString(), rnd.Next(1, 100).ToString(), rnd.Next(1, 100).ToString()));
            }
        }

        private ListViewItem AddToList(string name, string price, string trend)
        {
            string[] array = new string[3];
            array[0] = name;
            array[1] = price;
            array[2] = trend;

            return (new ListViewItem(array));
        }

        private void listView1_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            // Determine if clicked column is already the column that is being sorted.
            if (e.Column == lvwColumnSorter.SortColumn)
            {
                // Reverse the current sort direction for this column.
                if (lvwColumnSorter.Order == SortOrder.Ascending)
                {
                    lvwColumnSorter.Order = SortOrder.Descending;
                }
                else
                {
                    lvwColumnSorter.Order = SortOrder.Ascending;
                }
            }
            else
            {
                // Set the column number that is to be sorted; default to ascending.
                lvwColumnSorter.SortColumn = e.Column;
                lvwColumnSorter.Order = SortOrder.Ascending;
            }

            // Perform the sort with these new sort options.
            this.listView1.Sort();
        }

    }
}

ListViewColumnSorter.cs 包含

using System;
using System.Collections;
using System.Windows.Forms;

/// <summary>
/// This class is an implementation of the 'IComparer' interface.
/// </summary>
public class ListViewColumnSorter : IComparer
{
    /// <summary>
    /// Specifies the column to be sorted
    /// </summary>
    private int ColumnToSort;
    /// <summary>
    /// Specifies the order in which to sort (i.e. 'Ascending').
    /// </summary>
    private SortOrder OrderOfSort;
    /// <summary>
    /// Case insensitive comparer object
    /// </summary>
    private CaseInsensitiveComparer ObjectCompare;

    /// <summary>
    /// Class constructor.  Initializes various elements
    /// </summary>
    public ListViewColumnSorter()
    {
        // Initialize the column to '0'
        ColumnToSort = 0;

        // Initialize the sort order to 'none'
        OrderOfSort = SortOrder.None;

        // Initialize the CaseInsensitiveComparer object
        ObjectCompare = new CaseInsensitiveComparer();
    }

    /// <summary>
    /// This method is inherited from the IComparer interface.  It compares the two objects passed using a case insensitive comparison.
    /// </summary>
    /// <param name="x">First object to be compared</param>
    /// <param name="y">Second object to be compared</param>
    /// <returns>The result of the comparison. "0" if equal, negative if 'x' is less than 'y' and positive if 'x' is greater than 'y'</returns>
    public int Compare(object x, object y)
    {
        int compareResult;
        ListViewItem listviewX, listviewY;

        // Cast the objects to be compared to ListViewItem objects
        listviewX = (ListViewItem)x;
        listviewY = (ListViewItem)y;

        decimal num = 0;
        if (decimal.TryParse(listviewX.SubItems[ColumnToSort].Text, out num))
        {
            compareResult = decimal.Compare(num, Convert.ToDecimal(listviewY.SubItems[ColumnToSort].Text));
        }
        else 
        {
            // Compare the two items
            compareResult = ObjectCompare.Compare(listviewX.SubItems[ColumnToSort].Text, listviewY.SubItems[ColumnToSort].Text);
        }

        // Calculate correct return value based on object comparison
        if (OrderOfSort == SortOrder.Ascending)
        {
            // Ascending sort is selected, return normal result of compare operation
            return compareResult;
        }
        else if (OrderOfSort == SortOrder.Descending)
        {
            // Descending sort is selected, return negative result of compare operation
            return (-compareResult);
        }
        else
        {
            // Return '0' to indicate they are equal
            return 0;
        }
    }

    /// <summary>
    /// Gets or sets the number of the column to which to apply the sorting operation (Defaults to '0').
    /// </summary>
    public int SortColumn
    {
        set
        {
            ColumnToSort = value;
        }
        get
        {
            return ColumnToSort;
        }
    }

    /// <summary>
    /// Gets or sets the order of sorting to apply (for example, 'Ascending' or 'Descending').
    /// </summary>
    public SortOrder Order
    {
        set
        {
            OrderOfSort = value;
        }
        get
        {
            return OrderOfSort;
        }
    }

}

【讨论】:

    【解决方案5】:

    我的解决方案是在您单击列标题时对 listView 项目进行排序。

    您可以指定每列的类型。

    listView.ListViewItemSorter = new ListViewColumnSorter();
    listView.ListViewItemSorter.ColumnsTypeComparer.Add(0, DateTime);
    listView.ListViewItemSorter.ColumnsTypeComparer.Add(1, int);
    

    就是这样!

    C# 类:

    using System.Collections;
    using System.Collections.Generic;
    using EDV;
    
    namespace System.Windows.Forms
    {
        /// <summary>
        /// Cette classe est une implémentation de l'interface 'IComparer' pour le tri des items de ListView. Adapté de http://support.microsoft.com/kb/319401.
        /// </summary>
        /// <remarks>Intégré par EDVariables.</remarks>
        public class ListViewColumnSorter : IComparer
        {
            /// <summary>
            /// Spécifie la colonne à trier
            /// </summary>
            private int ColumnToSort;
            /// <summary>
            /// Spécifie l'ordre de tri (en d'autres termes 'Croissant').
            /// </summary>
            private SortOrder OrderOfSort;
            /// <summary>
            /// Objet de comparaison ne respectant pas les majuscules et minuscules
            /// </summary>
            private CaseInsensitiveComparer ObjectCompare;
    
            /// <summary>
            /// Constructeur de classe.  Initialise la colonne sur '0' et aucun tri
            /// </summary>
            public ListViewColumnSorter()
                : this(0, SortOrder.None) { }
    
            /// <summary>
            /// Constructeur de classe.  Initializes various elements
            /// <param name="columnToSort">Spécifie la colonne à trier</param>
            /// <param name="orderOfSort">Spécifie l'ordre de tri</param>
            /// </summary>
            public ListViewColumnSorter(int columnToSort, SortOrder orderOfSort)
            {
                // Initialise la colonne
                ColumnToSort = columnToSort;
    
                // Initialise l'ordre de tri
                OrderOfSort = orderOfSort;
    
                // Initialise l'objet CaseInsensitiveComparer
                ObjectCompare = new CaseInsensitiveComparer();
    
                // Dictionnaire de comparateurs
                ColumnsComparer = new Dictionary<int, IComparer>();
                ColumnsTypeComparer = new Dictionary<int, Type>();
    
            }
    
            /// <summary>
            /// Cette méthode est héritée de l'interface IComparer.  Il compare les deux objets passés en effectuant une comparaison 
            ///qui ne tient pas compte des majuscules et des minuscules.
            /// <br/>Si le comparateur n'existe pas dans ColumnsComparer, CaseInsensitiveComparer est utilisé.
            /// </summary>
            /// <param name="x">Premier objet à comparer</param>
            /// <param name="x">Deuxième objet à comparer</param>
            /// <returns>Le résultat de la comparaison. "0" si équivalent, négatif si 'x' est inférieur à 'y' 
            ///et positif si 'x' est supérieur à 'y'</returns>
            public int Compare(object x, object y)
            {
                int compareResult;
                ListViewItem listviewX, listviewY;
    
                // Envoit les objets à comparer aux objets ListViewItem
                listviewX = (ListViewItem)x;
                listviewY = (ListViewItem)y;
    
                if (listviewX.SubItems.Count < ColumnToSort + 1 || listviewY.SubItems.Count < ColumnToSort + 1)
                    return 0;
    
                IComparer objectComparer = null;
                Type comparableType = null;
                if (ColumnsComparer == null || !ColumnsComparer.TryGetValue(ColumnToSort, out objectComparer))
                    if (ColumnsTypeComparer == null || !ColumnsTypeComparer.TryGetValue(ColumnToSort, out comparableType))
                        objectComparer = ObjectCompare;
    
                // Compare les deux éléments
                if (comparableType != null) {
                    //Conversion du type
                    object valueX = listviewX.SubItems[ColumnToSort].Text;
                    object valueY = listviewY.SubItems[ColumnToSort].Text;
                    if (!edvTools.TryParse(ref valueX, comparableType) || !edvTools.TryParse(ref valueY, comparableType))
                        return 0;
                    compareResult = (valueX as IComparable).CompareTo(valueY);
                }
                else
                    compareResult = objectComparer.Compare(listviewX.SubItems[ColumnToSort].Text, listviewY.SubItems[ColumnToSort].Text);
    
                // Calcule la valeur correcte d'après la comparaison d'objets
                if (OrderOfSort == SortOrder.Ascending) {
                    // Le tri croissant est sélectionné, renvoie des résultats normaux de comparaison
                    return compareResult;
                }
                else if (OrderOfSort == SortOrder.Descending) {
                    // Le tri décroissant est sélectionné, renvoie des résultats négatifs de comparaison
                    return (-compareResult);
                }
                else {
                    // Renvoie '0' pour indiquer qu'ils sont égaux
                    return 0;
                }
            }
    
            /// <summary>
            /// Obtient ou définit le numéro de la colonne à laquelle appliquer l'opération de tri (par défaut sur '0').
            /// </summary>
            public int SortColumn
            {
                set
                {
                    ColumnToSort = value;
                }
                get
                {
                    return ColumnToSort;
                }
            }
    
            /// <summary>
            /// Obtient ou définit l'ordre de tri à appliquer (par exemple, 'croissant' ou 'décroissant').
            /// </summary>
            public SortOrder Order
            {
                set
                {
                    OrderOfSort = value;
                }
                get
                {
                    return OrderOfSort;
                }
            }
    
            /// <summary>
            /// Dictionnaire de comparateurs par colonne.
            /// <br/>Pendant le tri, si le comparateur n'existe pas dans ColumnsComparer, CaseInsensitiveComparer est utilisé.
            /// </summary>
            public Dictionary<int, IComparer> ColumnsComparer { get; set; }
    
            /// <summary>
            /// Dictionnaire de comparateurs par colonne.
            /// <br/>Pendant le tri, si le comparateur n'existe pas dans ColumnsTypeComparer, CaseInsensitiveComparer est utilisé.
            /// </summary>
            public Dictionary<int, Type> ColumnsTypeComparer { get; set; }
        }
    }
    

    初始化 ListView :

        <var>Visual.WIN.ctrlListView.OnShown</var>  : 
        eventSender.Columns.Clear();
        eventSender.SmallImageList = edvWinForm.ImageList16;
        eventSender.ListViewItemSorter = new ListViewColumnSorter();
        var col = eventSender.Columns.Add("Répertoire");
        col.Width = 160;
        col.ImageKey = "Domain";
        col = eventSender.Columns.Add("Fichier");
        col.Width = 180;
        col.ImageKey = "File";
        col = eventSender.Columns.Add("Date");
        col.Width = 120;
        col.ImageKey = "DateTime";
        eventSender.ListViewItemSorter.ColumnsTypeComparer.Add(col.Index, DateTime);
        col = eventSender.Columns.Add("Position");
        col.TextAlign = HorizontalAlignment.Right;
        col.Width = 80;
        col.ImageKey = "Num";
        eventSender.ListViewItemSorter.ColumnsTypeComparer.Add(col.Index, Int32);
    

    填写一个 ListView :

    <var>Visual.WIN.cmdSearch.OnClick</var>  : 
    //non récursif et sans fonction
        ..ctrlListView:Items.Clear();
        ..ctrlListView:Sorting = SortOrder.None;
        var group = ..ctrlListView:Groups.Add(DateTime.Now.ToString()
                    , Path.Combine(..cboDir:Text, ..ctrlPattern1:Text) + " contenant " + ..ctrlSearch1:Text);
        var perf =  Environment.TickCount;
    
        var files = new DirectoryInfo(..cboDir:Text).GetFiles(..ctrlPattern1:Text)
        var search = ..ctrlSearch1:Text;
        var ignoreCase = ..Search.IgnoreCase;
        //var result = new StringBuilder();
        var dirLength : int = ..cboDir:Text.Length;
        var position : int;
        var added : int = 0;
        for(var i : int = 0; i &lt; files.Length; i++){
            var file = files[i];
            if(search == ""
            || (position = File.ReadAllText(file.FullName).IndexOf(String(search)
                                , StringComparison(ignoreCase ? StringComparison.InvariantCultureIgnoreCase : StringComparison.InvariantCulture))) &gt; =0) {
    
            //  result.AppendLine(file.FullName.Substring(dirLength) + "\tPos : " + pkvFile.Value);
                var item = ..ctrlListView:Items.Add(file.FullName.Substring(dirLength));
                item.SubItems.Add(file.Name);
                item.SubItems.Add(File.GetLastWriteTime(file.FullName).ToString());
                item.SubItems.Add(position.ToString("# ### ##0"));
                item.Group = group;
                ++added;
            }
        }
        group.Header += " : " + added + "/" + files.Length + " fichier(s)"
                    + "  en " + (Environment.TickCount - perf).ToString("# ##0 msec");
    

    在 ListView 列上单击:

    <var>Visual.WIN.ctrlListView.OnColumnClick</var>  : 
    // Déterminer si la colonne sélectionnée est déjà la colonne triée.
    var sorter = eventSender.ListViewItemSorter;
    if ( eventArgs.Column == sorter .SortColumn )
    {
        // Inverser le sens de tri en cours pour cette colonne.
        if (sorter.Order == SortOrder.Ascending)
        {
            sorter.Order = SortOrder.Descending;
        }
        else
        {
            sorter.Order = SortOrder.Ascending;
        }
    }
    else
    {
        // Définir le numéro de colonne à trier ; par défaut sur croissant.
        sorter.SortColumn = eventArgs.Column;
        sorter.Order = SortOrder.Ascending;
    }
    
    // Procéder au tri avec les nouvelles options.
    eventSender.Sort();
    

    上面使用的函数edvTools.TryParse

    class edvTools {
        /// <summary>
        /// Tente la conversion d'une valeur suivant un type EDVType
        /// </summary>
        /// <param name="pValue">Référence de la valeur à convertir</param>
        /// <param name="pType">Type EDV en sortie</param>
        /// <returns></returns>
        public static bool TryParse(ref object pValue, System.Type pType)
        {
            int lIParsed;
            double lDParsed;
            string lsValue;
            if (pValue == null) return false;
            if (pType.Equals(typeof(bool))) {
                bool lBParsed;
                if (pValue is bool) return true;
                if (double.TryParse(pValue.ToString(), out lDParsed)) {
                    pValue = lDParsed != 0D;
                    return true;
                }
                if (bool.TryParse(pValue.ToString(), out lBParsed)) {
                    pValue = lBParsed;
                    return true;
                }
                else
                    return false;
            }
            if (pType.Equals(typeof(Double))) {
                if (pValue is Double) return true;
                if (double.TryParse(pValue.ToString(), out lDParsed)
                    || double.TryParse(pValue.ToString().Replace(NumberDecimalSeparatorNOT, NumberDecimalSeparator), out lDParsed)) {
                    pValue = lDParsed;
                    return true;
                }
                else
                    return false;
            }
            if (pType.Equals(typeof(int))) {
                if (pValue is int) return true;
                if (Int32.TryParse(pValue.ToString(), out lIParsed)) {
                    pValue = lIParsed;
                    return true;
                }
                else if (double.TryParse(pValue.ToString(), out lDParsed)) {
                    pValue = (int)lDParsed;
                    return true;
                }
                else
                    return false;
            }
            if (pType.Equals(typeof(Byte))) {
                if (pValue is byte) return true;
                byte lByte;
                if (Byte.TryParse(pValue.ToString(), out lByte)) {
                    pValue = lByte;
                    return true;
                }
                else if (double.TryParse(pValue.ToString(), out lDParsed)) {
                    pValue = (byte)lDParsed;
                    return true;
                }
                else
                    return false;
            }
            if (pType.Equals(typeof(long))) {
                long lLParsed;
                if (pValue is long) return true;
                if (long.TryParse(pValue.ToString(), out lLParsed)) {
                    pValue = lLParsed;
                    return true;
                }
                else if (double.TryParse(pValue.ToString(), out lDParsed)) {
                    pValue = (long)lDParsed;
                    return true;
                }
                else
                    return false;
            }
            if (pType.Equals(typeof(Single))) {
                if (pValue is float) return true;
                Single lSParsed;
                if (Single.TryParse(pValue.ToString(), out lSParsed)
                    || Single.TryParse(pValue.ToString().Replace(NumberDecimalSeparatorNOT, NumberDecimalSeparator), out lSParsed)) {
                    pValue = lSParsed;
                    return true;
                }
                else
                    return false;
            }
            if (pType.Equals(typeof(DateTime))) {
                if (pValue is DateTime) return true;
                DateTime lDTParsed;
                if (DateTime.TryParse(pValue.ToString(), out lDTParsed)) {
                    pValue = lDTParsed;
                    return true;
                }
                else if (pValue.ToString().Contains("UTC")) //Date venant de JScript
                {
                    if (_MonthsUTC == null) InitMonthsUTC();
                    string[] lDateParts = pValue.ToString().Split(' ');
                    lDTParsed = new DateTime(int.Parse(lDateParts[5]), _MonthsUTC[lDateParts[1]], int.Parse(lDateParts[2]));
                    lDateParts = lDateParts[3].ToString().Split(':');
                    pValue = lDTParsed.AddSeconds(int.Parse(lDateParts[0]) * 3600 + int.Parse(lDateParts[1]) * 60 + int.Parse(lDateParts[2]));
                    return true;
                }
                else
                    return false;
    
            }
            if (pType.Equals(typeof(Array))) {
                if (pValue is System.Collections.ICollection || pValue is System.Collections.ArrayList)
                    return true;
                return pValue is System.Data.DataTable
                    || pValue is string && (pValue as string).StartsWith("<");
            }
            if (pType.Equals(typeof(DataTable))) {
                return pValue is System.Data.DataTable
                    || pValue is string && (pValue as string).StartsWith("<");
    
            }
            if (pType.Equals(typeof(System.Drawing.Bitmap))) {
                return pValue is System.Drawing.Image || pValue is byte[];
    
            }
            if (pType.Equals(typeof(System.Drawing.Image))) {
                return pValue is System.Drawing.Image || pValue is byte[];
    
            }
            if (pType.Equals(typeof(System.Drawing.Color))) {
                if (pValue is System.Drawing.Color) return true;
                if (pValue is System.Drawing.KnownColor) {
                    pValue = System.Drawing.Color.FromKnownColor((System.Drawing.KnownColor)pValue);
                    return true;
                }
    
                int lARGB;
                if (!int.TryParse(lsValue = pValue.ToString(), out lARGB)) {
                    if (lsValue.StartsWith("Color [A=", StringComparison.InvariantCulture)) {
                        foreach (string lsARGB in lsValue.Substring("Color [".Length, lsValue.Length - "Color []".Length).Split(','))
                            switch (lsARGB.TrimStart().Substring(0, 1)) {
                                case "A":
                                    lARGB = int.Parse(lsARGB.Substring(2)) * 0x1000000;
                                    break;
                                case "R":
                                    lARGB += int.Parse(lsARGB.TrimStart().Substring(2)) * 0x10000;
                                    break;
                                case "G":
                                    lARGB += int.Parse(lsARGB.TrimStart().Substring(2)) * 0x100;
                                    break;
                                case "B":
                                    lARGB += int.Parse(lsARGB.TrimStart().Substring(2));
                                    break;
                                default:
                                    break;
                            }
                        pValue = System.Drawing.Color.FromArgb(lARGB);
                        return true;
                    }
                    if (lsValue.StartsWith("Color [", StringComparison.InvariantCulture)) {
                        pValue = System.Drawing.Color.FromName(lsValue.Substring("Color [".Length, lsValue.Length - "Color []".Length));
                        return true;
                    }
                    return false;
                }
                pValue = System.Drawing.Color.FromArgb(lARGB);
                return true;
            }
            if (pType.IsEnum) {
                try {
                    if (pValue == null) return false;
                    if (pValue is int || pValue is byte || pValue is ulong || pValue is long || pValue is double)
                        pValue = Enum.ToObject(pType, pValue);
                    else
                        pValue = Enum.Parse(pType, pValue.ToString());
                }
                catch {
                    return false;
                }
            }
            return true;
        }
    }
    

    【讨论】:

      【解决方案6】:

      我用过这个技巧

      private void lv_TavComEmpty_ColumnClick(object sender, ColumnClickEventArgs e)
              {
                  ListView lv = (ListView)sender;
      
                  //propriety SortOrder make me some problem on graphic layout
                  //i use this tag to set last order
                  if (lv.Tag == null || (int)lv.Tag > 0)
                  //if (lv.Sorting == SortOrder.Ascending)
                  {
                      ListViewItem[] tmp = lv.Items.Cast<ListViewItem>().OrderBy(t => t.SubItems[e.Column].Text).ToArray();
                      lv.Items.Clear();
                      lv.Items.AddRange(tmp);
      
                      lv.Tag = -1;
                      //lv.Sorting = SortOrder.Descending;
                  }
                  else
                  {
                      ListViewItem[] tmp = lv.Items.Cast<ListViewItem>().OrderByDescending(t => t.SubItems[e.Column].Text).ToArray();
                      lv.Items.Clear();
                      lv.Items.AddRange(tmp);
      
                      lv.Tag = +1;
                      //lv.Sorting = SortOrder.Ascending;
                  }
              }
      

      【讨论】:

      • 最佳答案 - 简短 - 紧凑。没有经过广泛测试,但似乎在细节视图上做得很好。
      【解决方案7】:

      我可以看到这个问题最初是在 5 年前发布的,当时程序员必须更加努力地工作才能获得他们想要的结果。 使用 Visual Studio 2012 及更高版本,懒惰的程序员可以进入 Listview 属性设置的设计视图,然后单击 Properties->Sorting,选择 Ascending。 还有许多其他属性特性可以获得懒惰(又名聪明)程序员可以利用的各种结果。

      【讨论】:

        【解决方案8】:

        聚会迟到了,这是一个简短的。它有以下限制:

        • 它只执行SubItems'Texts 的纯字符串排序
        • 它使用ListViewTag
        • 假定所有点击的列都将被填充

        您可以在其服务中注册和注销任何ListView;确保Sorting 设置为None..:

        public static class LvSort
        {
            static List<ListView> LVs = new List<ListView>();
            public static void registerLV(ListView lv)
            {
                if (!LVs.Contains(lv) && lv is ListView)
                {
                    LVs.Add(lv);
                    lv.ColumnClick +=Lv_ColumnClick;
                }
            }
            public static void unRegisterLV(ListView lv)
            {
                if (LVs.Contains(lv) && lv is ListView)
                {
                    LVs.Remove(lv);
                    lv.ColumnClick -=Lv_ColumnClick;
                }
            }
        
            private static void Lv_ColumnClick(object sender, ColumnClickEventArgs e)
            {
                ListView lv = sender as ListView;
                if (lv == null) return;
                int c = e.Column;
                bool asc = (lv.Tag == null) || ( lv.Tag.ToString() != c+"");
                var items = lv.Items.Cast<ListViewItem>().ToList();
                var sorted =  asc ? items.OrderByDescending(x => x.SubItems[c].Text).ToList() :
                                    items.OrderBy(x => x.SubItems[c].Text).ToList();
                lv.Items.Clear();
                lv.Items.AddRange(sorted.ToArray());
                if (asc) lv.Tag = c+""; else lv.Tag = null;
            }
        }
        

        注册只需做..:

        public Form1()
        {
            InitializeComponent();
            LvSort.registerLV(yourListView1);
        }
        

        更新:

        这是一个稍微扩展的版本,它可以让您使用您想出的任何排序规则对各种数据类型进行排序。您需要做的就是为您的数据编写一个特殊的字符串转换,将其添加到函数列表并标记您的列。为此,只需将附加了标记字符串的列名放在列的标签中。

        我添加了一个用于排序 DataTimes 和一个用于整数。

        此版本还将对锯齿状的 ListView 进行排序,即具有不同数量子项的列表视图。

        public static class LvCtl
        {
            static List<ListView> LVs = new List<ListView>();
        
            delegate string  StringFrom (string s);
        
            static Dictionary<string, StringFrom> funx = new Dictionary<string, StringFrom>();
        
            public static void registerLV(ListView lv)
            {
                if (!LVs.Contains(lv) && lv is ListView)
                {
                    LVs.Add(lv);
                    lv.ColumnClick +=Lv_ColumnClick;
        
                    funx.Add("", stringFromString);
                    for (int i = 0; i <  lv.Columns.Count; i++)
                    {
                        if (lv.Columns[i].Tag == null) continue;
                        string n = lv.Columns[i].Tag.ToString();
                        if (n == "") continue;
                        if (n.Contains("__date")) funx.Add(n, stringFromDate);
                        if (n.Contains("__int")) funx.Add(n, stringFromInt);
                        else funx.Add(n, stringFromString);
                    }
        
                }
            }
        
            static string stringFromString(string s)
            {
                return s;
            }
            static string stringFromInt(string s)
            {
                int i = 0;
                int.TryParse(s, out i);
                return i.ToString("00000") ;
            }
            static string stringFromDate(string s)
            {
                DateTime dt = Convert.ToDateTime(s);
                return dt.ToString("yyyy.MM.dd HH.mm.ss");
            }
        
            private static void Lv_ColumnClick(object sender, ColumnClickEventArgs e)
            {
                ListView lv = sender as ListView;
                if (lv == null) return;
        
        
                int c = e.Column;
                string nt = lv.Columns[c].Tag != null ? lv.Columns[c].Tag.ToString() : "";
                string n = nt.Replace("__", "§").Split('§')[0];
        
                bool asc = (lv.Tag == null) || ( lv.Tag.ToString() != c+"");
                var items = lv.Items.Cast<ListViewItem>().ToList();
                var sorted =  asc?
                    items.OrderByDescending(x =>  funx[nt]( c < x.SubItems.Count ?
                                            x.SubItems[c].Text: "")).ToList() :
                    items.OrderBy(x => funx[nt](c < x.SubItems.Count ?
                                  x.SubItems[c].Text : "")).ToList();
                lv.Items.Clear();
                lv.Items.AddRange(sorted.ToArray());
                if (asc) lv.Tag = c+""; else lv.Tag = null;
            }
        
            public static void unRegisterLV(ListView lv)
            {
                if (LVs.Contains(lv) && lv is ListView)
                {
                    LVs.Remove(lv);
                    lv.ColumnClick -=Lv_ColumnClick;
                }
            }
        }
        

        【讨论】:

          【解决方案9】:

          我会推荐你​​给你 datagridview,对于重的东西.. 它包括很多列表维没有的自动功能

          【讨论】:

            【解决方案10】:

            使用ListView.SortExpression

            当对多列进行排序时,这 属性包含逗号分隔 要排序的字段列表。

            【讨论】:

            • 这是关于 ASP.NET Web 控件,而不是 Windows 窗体。
            【解决方案11】:

            你可以像这样使用手动排序算法

            public void ListItemSorter(object sender, ColumnClickEventArgs e)
                {
                    ListView list = (ListView)sender;
                    int total = list.Items.Count;
                    list.BeginUpdate();
                    ListViewItem[] items = new ListViewItem[total];
                    for (int i = 0; i < total; i++)
                    {
                        int count = list.Items.Count;
                        int minIdx = 0;
                        for (int j = 1; j < count; j++)
                            if (list.Items[j].SubItems[e.Column].Text.CompareTo(list.Items[minIdx].SubItems[e.Column].Text) < 0)
                                minIdx = j;
                        items[i] = list.Items[minIdx];
                        list.Items.RemoveAt(minIdx);
                    }
                    list.Items.AddRange(items);
                    list.EndUpdate();
                }
            

            此方法使用 O^2 顺序和升序的选择排序。您可以将 '>' 更改为 '

            【讨论】:

              【解决方案12】:

              由于这仍然是一个热门话题,我想我可能会注意到我想出了一个动态解决方案来按列对列表视图进行排序。这是代码,以防其他人也想使用它。它几乎只涉及将列表视图项发送到数据表,按列名对数据表的默认视图进行排序(使用单击列的索引),然后使用 defaultview.totable() 方法覆盖该表。然后几乎只需将它们添加回列表视图。哇啦,它是按列排序的列表视图。

              public void SortListView(int Index)
                  {
                      DataTable TempTable = new DataTable();
                      //Add column names to datatable from listview
                      foreach (ColumnHeader iCol in MyListView.Columns)
                      {
                          TempTable.Columns.Add(iCol.Text);
                      }
                      //Create a datarow from each listviewitem and add it to the table
                      foreach (ListViewItem Item in MyListView.Items)
                      {
                           DataRow iRow = TempTable.NewRow();
                           // the for loop dynamically copies the data one by one instead of doing irow[i] = MyListView.Subitems[1]... so on
                          for (int i = 0; i < MyListView.Columns.Count; i++)
                          {
                              if (i == 0)
                              {
                                  iRow[i] = Item.Text;
                              }
                              else
                              {
                                  iRow[i] = Item.SubItems[i].Text;
                              }
                          }
                          TempTable.Rows.Add(iRow);
                      }
                      string SortType = string.Empty;
                      //LastCol is a public int variable on the form, and LastSort is public string variable
                      if (LastCol == Index)
                      {
                          if (LastSort == "ASC" || LastSort == string.Empty || LastSort == null)
                          {
                              SortType = "DESC";
                              LastSort = "DESC";
                          }
                          else
                          {
                              SortType = "ASC";
                              LastSort = "ASC";
                          }
                      }
                      else
                      {
                          SortType = "DESC";
                          LastSort = "DESC";
                      }
                      LastCol = Index;
                      MyListView.Items.Clear();
                      //Sort it based on the column text clicked and the sort type (asc or desc)
                      TempTable.DefaultView.Sort = MyListView.Columns[Index].Text + " " + SortType;
                      TempTable = TempTable.DefaultView.ToTable();
                      //Create a listview item from the data in each row
                      foreach (DataRow iRow in TempTable.Rows)
                      {
                          ListViewItem Item = new ListViewItem();
                          List<string> SubItems = new List<string>();
                          for (int i = 0; i < TempTable.Columns.Count; i++)
                          {
                              if (i == 0)
                              {
                                  Item.Text = iRow[i].ToString();
                              }
                              else
                              {
                                  SubItems.Add(iRow[i].ToString());
                              }
                          }
                          Item.SubItems.AddRange(SubItems.ToArray());
                          MyListView.Items.Add(Item);
                      }
                  }
              

              此方法是动态的,因为它使用现有的列名,并且不需要您知道每列的索引或名称,甚至不需要知道列表视图/数据表中有多少列。您可以通过为 listview.columnclick 然后为 SortListView(e.column) 创建事件来调用它。

              【讨论】:

                【解决方案13】:

                根据 RedEye 指出的示例,这是一个需要较少代码的类:
                它假定列总是以相同的方式排序,因此它在内部处理
                ColumnClick 事件接收器:

                public class ListViewColumnSorterExt : IComparer {
                    /// <summary>
                    /// Specifies the column to be sorted
                    /// </summary>
                    private int ColumnToSort;
                    /// <summary>
                    /// Specifies the order in which to sort (i.e. 'Ascending').
                    /// </summary>
                    private SortOrder OrderOfSort;
                    /// <summary>
                    /// Case insensitive comparer object
                    /// </summary>
                    private CaseInsensitiveComparer ObjectCompare;
                
                    private ListView listView;
                    /// <summary>
                    /// Class constructor.  Initializes various elements
                    /// </summary>
                    public ListViewColumnSorterExt(ListView lv) {
                        listView = lv;
                        listView.ListViewItemSorter = this;
                        listView.ColumnClick += new ColumnClickEventHandler(listView_ColumnClick);
                
                        // Initialize the column to '0'
                        ColumnToSort = 0;
                
                        // Initialize the sort order to 'none'
                        OrderOfSort = SortOrder.None;
                
                        // Initialize the CaseInsensitiveComparer object
                        ObjectCompare = new CaseInsensitiveComparer();
                    }
                
                    private void listView_ColumnClick(object sender, ColumnClickEventArgs e) {
                        ReverseSortOrderAndSort(e.Column, (ListView)sender);
                    }
                
                    /// <summary>
                    /// This method is inherited from the IComparer interface.  It compares the two objects passed using a case insensitive comparison.
                    /// </summary>
                    /// <param name="x">First object to be compared</param>
                    /// <param name="y">Second object to be compared</param>
                    /// <returns>The result of the comparison. "0" if equal, negative if 'x' is less than 'y' and positive if 'x' is greater than 'y'</returns>
                    public int Compare(object x, object y) {
                        int compareResult;
                        ListViewItem listviewX, listviewY;
                
                        // Cast the objects to be compared to ListViewItem objects
                        listviewX = (ListViewItem)x;
                        listviewY = (ListViewItem)y;
                
                        // Compare the two items
                        compareResult = ObjectCompare.Compare(listviewX.SubItems[ColumnToSort].Text, listviewY.SubItems[ColumnToSort].Text);
                
                        // Calculate correct return value based on object comparison
                        if (OrderOfSort == SortOrder.Ascending) {
                            // Ascending sort is selected, return normal result of compare operation
                            return compareResult;
                        }
                        else if (OrderOfSort == SortOrder.Descending) {
                            // Descending sort is selected, return negative result of compare operation
                            return (-compareResult);
                        }
                        else {
                            // Return '0' to indicate they are equal
                            return 0;
                        }
                    }
                
                    /// <summary>
                    /// Gets or sets the number of the column to which to apply the sorting operation (Defaults to '0').
                    /// </summary>
                    private int SortColumn {
                        set {
                            ColumnToSort = value;
                        }
                        get {
                            return ColumnToSort;
                        }
                    }
                
                    /// <summary>
                    /// Gets or sets the order of sorting to apply (for example, 'Ascending' or 'Descending').
                    /// </summary>
                    private SortOrder Order {
                        set {
                            OrderOfSort = value;
                        }
                        get {
                            return OrderOfSort;
                        }
                    }
                
                    private void ReverseSortOrderAndSort(int column, ListView lv) {
                        // Determine if clicked column is already the column that is being sorted.
                        if (column == this.SortColumn) {
                            // Reverse the current sort direction for this column.
                            if (this.Order == SortOrder.Ascending) {
                                this.Order = SortOrder.Descending;
                            }
                            else {
                                this.Order = SortOrder.Ascending;
                            }
                        }
                        else {
                            // Set the column number that is to be sorted; default to ascending.
                            this.SortColumn = column;
                            this.Order = SortOrder.Ascending;
                        }
                
                        // Perform the sort with these new sort options.
                        lv.Sort();
                    }
                }  
                

                假设您对排序选项感到满意,则类属性是私有的

                您需要编写的唯一代码是:

                在表单声明中

                private ListViewColumnSorterExt listViewColumnSorter;  
                

                在表单构造函数中

                listViewColumnSorter = new ListViewColumnSorterExt(ListView1);  
                

                ...你就完成了。

                那么处理多个 ListView 的单个排序器呢?

                public class MultipleListViewColumnSorter {
                    private List<ListViewColumnSorterExt> sorters;
                
                    public MultipleListViewColumnSorter() {
                        sorters = new List<ListViewColumnSorterExt>();
                    }
                
                    public void AddListView(ListView lv) {
                        sorters.Add(new ListViewColumnSorterExt(lv));
                    }
                }  
                

                在表单声明中

                private MultipleListViewColumnSorter listViewSorter = new MultipleListViewColumnSorter();  
                

                在表单构造函数中

                listViewSorter.AddListView(ListView1);  
                listViewSorter.AddListView(ListView2);  
                // ... and so on ...  
                

                【讨论】:

                  【解决方案14】:

                  我稍微修改了微软的例子:https://support.microsoft.com/en-us/kb/319401

                  此方法只会排序一次以升序排序。我的修改使它成为双向排序。

                  public class ListViewItemComparer : IComparer
                  {
                      private int col;
                      bool bAsc = false;
                      public ListViewItemComparer()
                      {
                          col = 0;
                      }
                      public ListViewItemComparer(int column, bool b)
                      {
                          col = column;
                          bAsc = b;
                      }
                      public int Compare(object x, object y)
                      {
                          if (bAsc)
                          {
                              return String.Compare(((ListViewItem)x).SubItems[col].Text, ((ListViewItem)y).SubItems[col].Text);
                              bAsc = false;
                          }
                          else
                          {
                              return String.Compare(((ListViewItem)y).SubItems[col].Text, ((ListViewItem)x).SubItems[col].Text);
                              bAsc = true;
                          }
                      }
                  
                  }
                  

                  然后,每当单击列标题时,我都会创建此类的一个对象

                          bool sortAscending = false;
                          private void inventoryList_ColumnClick(object sender, ColumnClickEventArgs e)
                          {
                  
                              if (!sortAscending)
                              {
                                  sortAscending = true;
                              }
                              else
                              {
                                  sortAscending = false;
                              }
                              this.inventoryList.ListViewItemSorter = new ListViewItemComparer(e.Column, sortAscending);
                  
                          }
                  

                  【讨论】:

                    【解决方案15】:

                    我使用了与其他人似乎使用的相同的基类,只是我对其进行了更改以允许字符串、日期和数字排序。

                    您可以像这样使用支持字段对其进行初始化:

                    private readonly ListViewColumnSorterExt fileSorter;
                    ...
                    public Form1()
                    {
                        InitializeComponent();
                        fileSorter = new ListViewColumnSorterExt(myListView);
                    }
                    

                    代码如下:

                    public class ListViewColumnSorterExt : IComparer
                    {
                        /// <summary>
                        /// Specifies the column to be sorted
                        /// </summary>
                        private int ColumnToSort;
                        /// <summary>
                        /// Specifies the order in which to sort (i.e. 'Ascending').
                        /// </summary>
                        private SortOrder OrderOfSort;
                        /// <summary>
                        /// Case insensitive comparer object
                        /// </summary>
                        private CaseInsensitiveComparer ObjectCompare;
                    
                        private ListView listView;
                        /// <summary>
                        /// Class constructor.  Initializes various elements
                        /// </summary>
                        public ListViewColumnSorterExt(ListView lv)
                        {
                            listView = lv;
                            listView.ListViewItemSorter = this;
                            listView.ColumnClick += new ColumnClickEventHandler(listView_ColumnClick);
                    
                            // Initialize the column to '0'
                            ColumnToSort = 0;
                    
                            // Initialize the sort order to 'none'
                            OrderOfSort = SortOrder.None;
                    
                            // Initialize the CaseInsensitiveComparer object
                            ObjectCompare = new CaseInsensitiveComparer();
                        }
                    
                        private void listView_ColumnClick(object sender, ColumnClickEventArgs e)
                        {
                            ReverseSortOrderAndSort(e.Column, (ListView)sender);
                        }
                    
                        /// <summary>
                        /// This method is inherited from the IComparer interface.  It compares the two objects passed using a case insensitive comparison.
                        /// </summary>
                        /// <param name="x">First object to be compared</param>
                        /// <param name="y">Second object to be compared</param>
                        /// <returns>The result of the comparison. "0" if equal, negative if 'x' is less than 'y' and positive if 'x' is greater than 'y'</returns>
                        public int Compare(object x, object y)
                        {
                            int compareResult;
                            ListViewItem listviewX, listviewY;
                    
                            // Cast the objects to be compared to ListViewItem objects
                            listviewX = (ListViewItem)x;
                            listviewY = (ListViewItem)y;
                    
                            if (decimal.TryParse(listviewX.SubItems[ColumnToSort].Text, out decimal dx) && decimal.TryParse(listviewY.SubItems[ColumnToSort].Text, out decimal dy))
                            {
                                //compare the 2 items as doubles
                                compareResult = decimal.Compare(dx, dy);
                            }
                            else if (DateTime.TryParse(listviewX.SubItems[ColumnToSort].Text, out DateTime dtx) && DateTime.TryParse(listviewY.SubItems[ColumnToSort].Text, out DateTime dty))
                            {
                                //compare the 2 items as doubles
                                compareResult = DateTime.Compare(dtx, dty);
                            }
                            else
                            {
                                // Compare the two items
                                compareResult = ObjectCompare.Compare(listviewX.SubItems[ColumnToSort].Text, listviewY.SubItems[ColumnToSort].Text);
                            }
                            // Calculate correct return value based on object comparison
                            if (OrderOfSort == SortOrder.Ascending)
                            {
                                // Ascending sort is selected, return normal result of compare operation
                                return compareResult;
                            }
                            else if (OrderOfSort == SortOrder.Descending)
                            {
                                // Descending sort is selected, return negative result of compare operation
                                return (-compareResult);
                            }
                            else
                            {
                                // Return '0' to indicate they are equal
                                return 0;
                            }
                        }
                    
                        /// <summary>
                        /// Gets or sets the number of the column to which to apply the sorting operation (Defaults to '0').
                        /// </summary>
                        private int SortColumn
                        {
                            set
                            {
                                ColumnToSort = value;
                            }
                            get
                            {
                                return ColumnToSort;
                            }
                        }
                    
                        /// <summary>
                        /// Gets or sets the order of sorting to apply (for example, 'Ascending' or 'Descending').
                        /// </summary>
                        private SortOrder Order
                        {
                            set
                            {
                                OrderOfSort = value;
                            }
                            get
                            {
                                return OrderOfSort;
                            }
                        }
                    
                        private void ReverseSortOrderAndSort(int column, ListView lv)
                        {
                            // Determine if clicked column is already the column that is being sorted.
                            if (column == this.SortColumn)
                            {
                                // Reverse the current sort direction for this column.
                                if (this.Order == SortOrder.Ascending)
                                {
                                    this.Order = SortOrder.Descending;
                                }
                                else
                                {
                                    this.Order = SortOrder.Ascending;
                                }
                            }
                            else
                            {
                                // Set the column number that is to be sorted; default to ascending.
                                this.SortColumn = column;
                                this.Order = SortOrder.Ascending;
                            }
                    
                            // Perform the sort with these new sort options.
                            lv.Sort();
                        }
                    }
                    

                    如果您想根据排序顺序分配图标,则将图像列表添加到 Listview 并确保更新以下示例以反映用于排序的图像名称(您可以分配它们导入它们时的任何名称)。将上面的 listView_ColumnClick 更新为如下内容:

                    private void listView_ColumnClick(object sender, ColumnClickEventArgs e)
                    {
                        if (sender is ListView lv)
                        {
                            ReverseSortOrderAndSort(e.Column, lv);
                    
                            if (   lv.Columns[e.Column].ImageList.Images.Keys.Contains("Ascending") 
                                && lv.Columns[e.Column].ImageList.Images.Keys.Contains("Descending"))
                            {
                                switch (Order)
                                {
                                    case SortOrder.Ascending:
                                        lv.Columns[e.Column].ImageKey = "Ascending";
                                        break;
                                    case SortOrder.Descending:
                                        lv.Columns[e.Column].ImageKey = "Descending";
                                        break;
                                    case SortOrder.None:
                                        lv.Columns[e.Column].ImageKey = string.Empty;
                                        break;
                    
                                }
                            }
                    
                        }
                    }
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2013-11-09
                      • 2012-03-10
                      相关资源
                      最近更新 更多