简体   繁体   English

按列对ListView排序

[英]Sorting A ListView By Column

Currently I use a custom sorter on the listview, and i can sort the listview each time i click on the FIRST column, but it won't sort by other columns. 目前我在listview上使用自定义排序器,每次单击FIRST列时我都可以对listview进行排序,但不会按其他列排序。

SortStyle: Variable to determine whether it is Ascending Sort, or Descending. SortStyle:变量,用于确定它是Ascending Sort还是Descending。

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

This works fine when sorting for the first column, but if you were to do it on any other column, it would just sort by the first column. 在为第一列排序时,这可以正常工作,但如果您要在任何其他列上执行此操作,它将只按第一列排序。 Is there a way to sort by the column clicked? 有没有办法按列点击排序?

Forget about your custom sorter. 忘掉你的自定义分拣机。 Start over using the code at the following page. 重新开始使用下一页的代码。 It will show you how to define a class that inherits from the IComparer interface. 它将向您展示如何定义从IComparer接口继承的类。 Each line is commented out, so you can actually see what is happening. 每行都已注释掉,因此您可以实际查看正在发生的事情。 The only potential complication is how you are retrieving your Listview Items from your Listview control. 唯一可能的复杂因素是如何从Listview控件中检索Listview项。 Get those squared away and all you need to do is copy and paste the IComparer interface class and the columnClick method. 得到那些平方,你需要做的就是复制并粘贴IComparer接口类和columnClick方法。

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

If you are starting out with a ListView, do yourself a huge favour and use an ObjectListView instead. 如果您开始使用ListView,请自己做一个大忙,并使用ObjectListView ObjectListView is an open source wrapper around .NET WinForms ListView, which makes the ListView much easier to use and solves lots of common problems for you. ObjectListView是.NET WinForms ListView的开源包装器,它使ListView更易于使用,并为您解决了许多常见问题。 Sorting by column click is one of the many things it handles for you automatically. 按列排序是自动处理的众多内容之一。

Seriously, you will never regret using an ObjectListView instead of a normal ListView. 说真的,你永远不会后悔使用ObjectListView而不是普通的ListView。

I sort using column name to set any sorting specifics that may need to be handled based on data type stored in the column and or if the column has already been sorted on(asc/desc). 我使用列名来排序,根据存储在列中的数据类型设置可能需要处理的任何排序细节,或者如果列已经排序(asc / desc)。 Here's a snippet from my ColumnClick event handler. 这是我的ColumnClick事件处理程序的片段。

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

Below is my ListViewItemComparer 下面是我的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;
        }
    }
}

Made minor changes to the article here to accommodate sorting of both string and numeric values in ListView. 对文章作了小的改动这里 ,以适应字符串和ListView中数值的排序。

Form1.cs contains 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 contains 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;
        }
    }

}

My solution is a class to sort listView items when you click on column header. 我的解决方案是在单击列标题时对listView项进行排序的类。

You can specify the type of each column. 您可以指定每列的类型。

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

That's it ! 而已 !

The C# class : 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; }
    }
}

Initializing a ListView : 初始化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);

Fill a ListView : 填写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");

On ListView column click : 在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();

Function edvTools.TryParse used above 上面使用的函数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;
    }
}

I can see that this question was originally posted 5 yrs ago when programmers had to work harder to get their desired results. 我可以看到这个问题最初是在5年前发布的,当时程序员必须更加努力地获得他们想要的结果。 With Visual Studio 2012 and beyond, a lazy programmer can go the Design View for the Listview properties settings, and click on Properties->Sorting, choose Ascending. 使用Visual Studio 2012及更高版本,懒惰的程序员可以进入Listview属性设置的Design View,然后单击Properties-> Sorting,选择Ascending。 There are plenty of other properties features to obtain the various results a lazy (aka smart) programmer can leverage. 还有很多其他属性功能可以获得懒惰(又称智能)程序员可以利用的各种结果。

Late to the party, here is a short one. 晚会,这是一个短暂的。 It has these limitations: 它有以下局限:

  • It only does a plain string sort of the SubItems ' Texts 它只对SubItemsTexts进行简单的字符串排序
  • It uses the ListView 's Tag 它使用ListViewTag
  • It assumes all clicked columns will be filled 它假定所有单击的列都将被填充

You can register & unregister any ListView to its service; 您可以注册和取消注册任何ListView到其服务; make sure the Sorting is set to None ..: 确保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;
    }
}

To register simply do..: 注册只需做..:

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

Update: 更新:

Here is a slightly extended version that will let you sort all sorts of data types using any sorting rule you come up with. 这是一个稍微扩展的版本,它允许您使用您提出的任何排序规则对各种数据类型进行排序。 All you need to do is write a special string conversion for your data, add it to the function list and mark your columns. 您需要做的就是为数据编写特殊的字符串转换,将其添加到函数列表并标记列。 To do so simply put the column names appended with a marker string in the columns' Tags. 为此,只需在列标记中添加标记字符串后面的列名称即可。

I have added one for sorting DataTimes and one for integers. 我添加了一个用于排序DataTimes和一个用于整数。

This version will also sort jagged ListViews, ie those with different numbers of subitems. 此版本还将对锯齿状ListView进行排序,即具有不同子项数量的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;
        }
    }
}

我会推荐你​​datagridview,重要的东西..它包括很多汽车功能listviwe没有

Use the ListView.SortExpression . 使用ListView.SortExpression

When multiple columns are sorted, this property contains a comma-separated list of the fields to sort by. 排序多个列时,此属性包含要排序的字段的逗号分隔列表。

You can use a manual sorting algorithm like this 您可以使用这样的手动排序算法

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

this method uses selection sort in O^2 order and as Ascending. 此方法使用O ^ 2顺序中的选择排序和Ascending。 You can change the '>' with '<' for a descending or add an argument for this method. 您可以使用“<”更改“>”以降序或为此方法添加参数。 It sorts any column that is clicked and works perfect for small amount of data. 它对任何单击的列进行排序,适用于少量数据。

Since this is still a top viewed thread, I thought I might note that I came up with a dynamic solution to sort the listview by column. 由于这仍然是一个顶级浏览的线程,我想我可能会注意到我想出了一个动态解决方案来按列对列表视图进行排序。 Here's the code just in case someone else wants to use it as well. 这是代码,以防万一其他人也想使用它。 It pretty much just involves sending the listview items to a datatable, sorting the default view of the datatable by the column name (using the index of the clicked column), and then overwriting that table with the defaultview.totable() method. 它几乎只涉及将listview项发送到数据表,按列名对数据表的默认视图进行排序(使用单击列的索引),然后使用defaultview.totable()方法覆盖该表。 Then pretty much just add them back to the listview. 然后几乎只是将它们添加回列表视图。 And wa la, its a sorted listview by column. 并且wa la,它是按列排序的列表视图。

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

This method is dynamic as it uses the existing column name and doesn't require you to know the index or name of each column or even how many columns are in the listview/datatable. 此方法是动态的,因为它使用现有列名称,并且不需要您知道每列的索引或名称,甚至不需要知道listview / datatable中有多少列。 You can call it by doing creating an event for the listview.columnclick and then SortListView(e.column). 您可以通过为listview.columnclick创建事件然后SortListView(e.column)来调用它。

Based on the example pointed by RedEye, here's a class that needs less code : 根据RedEye指出的示例,这是一个需要较少代码的类:
it assumes that columns are always sorted in the same way, so it handles the 它假设列始终以相同的方式排序,因此它处理
ColumnClick event sink internally : 内部的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();
    }
}  

Assuming you're happy with the sort options, the class properties are private . 假设您对排序选项感到满意,则类属性是私有的

The only code you need to write is : 您需要编写的唯一代码是:

in Form declarations 在表单声明中

private ListViewColumnSorterExt listViewColumnSorter;  

in Form constructor 在Form构造函数中

listViewColumnSorter = new ListViewColumnSorterExt(ListView1);  

... and you're done. ......你已经完成了。

And what about a single sorter that handles multiple ListViews ? 那么处理多个ListView的单个分拣机呢?

public class MultipleListViewColumnSorter {
    private List<ListViewColumnSorterExt> sorters;

    public MultipleListViewColumnSorter() {
        sorters = new List<ListViewColumnSorterExt>();
    }

    public void AddListView(ListView lv) {
        sorters.Add(new ListViewColumnSorterExt(lv));
    }
}  

in Form declarations 在表单声明中

private MultipleListViewColumnSorter listViewSorter = new MultipleListViewColumnSorter();  

in Form constructor 在Form构造函数中

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

I slightly modified the example from Microsoft: https://support.microsoft.com/en-us/kb/319401 我稍微修改了Microsoft的示例: https//support.microsoft.com/en-us/kb/319401

This method will only sort once to sort ascending. 此方法仅排序一次以升序排序。 My modifications make it sort both ways. 我的修改使它有两种方式。

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

}

Then I create an object of this class whenever a column header is clicked 然后,只要单击列标题,我就会创建此类的对象

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

        }

i used this trick 我用这个技巧

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

I used the same base class as that what the others seem to use only I altered it as to allow for string, date and numerical sorting. 我使用了与其他人似乎只使用相同的基类,我将其更改为允许字符串,日期和数字排序。

You can initialize it using a backing-field like so: 您可以使用支持字段对其进行初始化,如下所示:

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

Here is the code: 这是代码:

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

If you'd like to assign icons in regards to the sort order then add an image list to the Listview and make sure you update the below sample to reflect the names of your images that you use for sorting (you can assign them any name when you import them). 如果您要分配关于排序顺序的图标,请将图像列表添加到Listview,并确保更新以下示例以反映用于排序的图像的名称(您可以在分配时指定任何名称)你导入它们)。 Update the above listView_ColumnClick to something like this: 将以上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;

            }
        }

    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM