7
votes

Comment trier les entiers dans une liste

Comment puis-je trier les colonnes d'entiers dans une liste de liste

C #, .NET 2.0, Winform

System.Windows.Forms.ListView


2 commentaires

Asp.net? Formulaires Windows?


J'ai édité ma réponse pour inclure un exemple complet, qui peut trier comme texte et numérique


7 Réponses :


0
votes

Je le ferais dans la source de données (modèle) au lieu de la vue. Triez-le là-bas et il devrait le mettre à jour dans la vue via la base de données.


3 commentaires

Vous voulez dire trier la source de données, la table de données de mon instance, puis recharger la liste de liste une fois que jamais une colonne est cliquée?


Non, mauvaise pratique à recharger à chaque fois. Google "Soreur d'élément ListView" et il vous montrera comment trier par chaque colonne.


Oups ... ne savait pas que c'était pour le formulaire Windows. Je viens de supposer WPF.



21
votes

Voici comment j'ai accompli de pouvoir trier sur plusieurs colonnes et pouvoir trier chaque colonne en tant que numéro ou en tant que texte.

Utilisez d'abord cette classe: P>

private void lvSeries_ColumnClick(object sender, ColumnClickEventArgs e)
    {
        Sorter s = (Sorter)lvSeries.ListViewItemSorter;
        s.Column = e.Column;

        if (s.Order == System.Windows.Forms.SortOrder.Ascending)
        {
            s.Order = System.Windows.Forms.SortOrder.Descending;
        }
        else
        {
            s.Order = System.Windows.Forms.SortOrder.Ascending;
        }
        lvSeries.Sort();
    }


3 commentaires

@Neil: Cela les trie comme texte par défaut. Par exemple. 100 vient avant 3. Cependant, vous pouvez trier l'INT correctement avec Personnalisé ListVieveviePorter.


J'ai suivi l'exemple à support.microsoft.com/kb/319401 mais il ne trie toujours pas Les entiers correctement.wront du texte, comment définissez-vous la colonne par défaut pour trier. Il trie juste bien sur la colonne 1 mais je ne trouve que la propriété de régler la colonne pour trier.


Geate!, Je viens d'utiliser de nombreuses pages qui affichent le nom de la colonne de grille comme 'id' . Donc, j'ai été changé si (l1.listview.columns [colonne] .tag.tostring () == "numérique") à if (l1.listview.columns [colonne] .. Text.toupper.indexof ("id")> -1 . C'est le travail. Merci pour la part!



4
votes

Vous devrez créer une classe qui implémente le Icomarer code> interface (le non générique). Dans cette classe, vous avez lu la Texte code> propriété à partir du bon sous-élément, convertissez-le sur INT, et faites la comparaison: xxx pré>

alors vous attribuez un tel comparateur à la propriété ListVievevemSorter et Invoquer la méthode de tri du contrôle ListView: P>

// create a comparer for column index 1 and assign it to the control, and sort
myListView.ListViewItemSorter = new IntegerComparer(1);
myListView.Sort();


3 commentaires

Certaines colonnes sont numériques d'autres sont du texte ... Devrais-je tester pour numériquement avant de tri?


J'ai effectué une fois un comparateur ListViewItem qui a examiné chaque paire d'éléments dans la méthode de comparaison, mais cela est devenu assez lent. Vous ferez mieux d'avoir des comparateurs distincts et de choisir celui à utiliser sur la base de la colonne en cours de tri, ou de la création d'une classe de comparateur où vous transmettez une valeur au constructeur indiquant si vous souhaitez effectuer une sorte de numéros, dates ou texte, puis passer dans la méthode de comparaison en fonction de cette valeur (qui était la solution que je suis allé dans ce cas).


Bonne idée. Mais j'ai créé une variable privée comme 'SortType' à l'intérieur de ma liste de comparaison de listeVoir la page.



5
votes

Si vous commencez avec une liste de réception, votre vie sera beaucoup plus facile si vous utilisez un ObjectListView à la place. ObjectListView est une enveloppe open source autour de Winforms Winforms Listview et il résout tous ces petits problèmes gênants qui font normalement travailler avec une vision de liste si frustrante. Par exemple, il trie automatiquement des intens pour que '100' vient après '3' (DateTimes, bools et tout le reste trie correctement).

Sérieusement, vous ne voudrez plus jamais revenir à une liste plaine de vue après avoir utilisé une liste ObjetListView.

Oui, je suis l'auteur - mais ça ne veut pas dire que je suis biaisé ... Ok, bien peut-être que ça fait :) Regardez ici pour des opinions d'autres personnes.


0 commentaires

0
votes

J'ai utilisé la classe de Neil-N mais j'ai modifié la déclaration IF pour tester la propriété Type au lieu de la propriété Tag. J'ai défini chaque colonne sur le numéro de type (au lieu de texte) qui avait une valeur entière dedans. Trier fonctionne bien. XXX


1 commentaires

Je ne sais pas si vous avez laissé quelque chose, mais ColonneHeader n'a pas de propriété .



0
votes
class ListViewAutoSorter : System.Collections.IComparer
{
    private int Column = 0;
    private System.Windows.Forms.SortOrder Order = SortOrder.Ascending;

    public ListViewAutoSorter(int Column, SortOrder Order)
    {
        this.Column = Column;
        this.Order = Order;
    }

    public int Compare(object x, object y) // IComparer Member
    {
        if (!(x is ListViewItem))
            return (0);
        if (!(y is ListViewItem))
            return (0);

        var l1 = (ListViewItem)x;
        var l2 = (ListViewItem)y;

        var value1 = 0.0;
        var value2 = 0.0;

        if (Double.TryParse(l1.SubItems[Column].Text, out value1) && 
            Double.TryParse(l2.SubItems[Column].Text, out value2))
        {
            if (Order == SortOrder.Ascending)
            {
                return value1.CompareTo(value2);
            }
            else
            {
                return value2.CompareTo(value1);
            }
        }
        else
        {
            var str1 = l1.SubItems[Column].Text;
            var str2 = l2.SubItems[Column].Text;

            if (Order == SortOrder.Ascending)
            {
                return str1.CompareTo(str2);
            }
            else
            {
                return str2.CompareTo(str1);
            }
        }
    }
}

0 commentaires

0
votes
Public Class Form1

Private Sub btnSortListView_Click(sender As Object, e As EventArgs) Handles btnSortListView.Click
        If btnSortListView.Text = "Sort Ascending" Then

            ListViewGar.ListViewItemSorter = New IntegerComparer(1)
            ListViewGar.Sort()

            btnSortListView.Text = "Not Sort"

        Else
            ListViewGar.ListViewItemSorter = New IntegerComparer(0)
            btnSortListView.Text = "Sort Ascending"
        End If

    End Sub
End Class

 Public Class IntegerComparer
    Implements System.Collections.IComparer

    Private _colIndex As Integer

    Public Sub New(ByVal colIndex As Integer)
        MyBase.New
        Me._colIndex = colIndex
    End Sub

    'Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer
    '    Dim nx As Integer = Integer.Parse(CType(x, ListViewItem).SubItems(Me._colIndex).Text)
    '    Dim ny As Integer = Integer.Parse(CType(y, ListViewItem).SubItems(Me._colIndex).Text)
    '    Return nx.CompareTo(ny)
    'End Function

    Private Function IComparer_Compare(x As Object, y As Object) As Integer Implements IComparer.Compare
        Dim nx As Integer = Integer.Parse(CType(x, ListViewItem).SubItems(Me._colIndex).Text)
        Dim ny As Integer = Integer.Parse(CType(y,ListViewItem).SubItems(Me._colIndex).Text)

        Dim colIndPlus As Integer = Me._colIndex
        Do While nx.CompareTo(ny) = 0
            colIndPlus = colIndPlus + 1
            nx = Integer.Parse(CType(x, ListViewItem).SubItems(colIndPlus).Text)
            ny = Integer.Parse(CType(y, ListViewItem).SubItems(colIndPlus).Text)
        Loop

        Return nx.CompareTo(ny)

    End Function
End Class
 image before and after sort

1 commentaires

La question concerne le C # ... mais la plupart peuvent probablement traduire.