web-dev-qa-db-fra.com

comment trier une datagridview par 2 colonnes

Comment trier un DataGridView en deux colonnes (croissant)? J'ai deux colonnes: day et status.

Si j'ai besoin de trier par une colonne, je fais:

this.dataGridView1.Sort (this.dataGridView1.Columns["day"], ListSortDirection.Ascending);

Mais pour deux?

12
user1112847

Si votre DataGridView est databound, vous pouvez trier votre vue Datatable et la lier de nouveau à datatable comme suit:

private DataGridView dataGridView1 = new DataGridView();
private BindingSource bindingSource1 = new BindingSource();

private void Form1_Load(object sender, System.EventArgs e)
{
    // Bind the DataGridView to the BindingSource        
    dataGridView1.DataSource = bindingSource1;
    SortDataByMultiColumns(); //Sort the Data
}

private void SortDataByMultiColumns()
{
    DataView view = dataTable1.DefaultView;
    view.Sort = "day ASC, status DESC"; 
    bindingSource1.DataSource = view; //rebind the data source
}

OU, sans utiliser bindingsource ni se lier directement à DataView:

private void SortDataByMultiColumns()
{
    DataView view = ds.Tables[0].DefaultView;
    view.Sort = "day ASC, status DESC"; 
    dataGridView1.DataSource = view; //rebind the data source
}
9
VS1

Ajouter une colonne cachée qui combine les deux et trier par cela.

6
linkerro

TLDR; J'ai une solution à deux lignes.

Je devais faire la même chose, mais après avoir recherché toutes ces méthodes compliquées en incluant un fichier .dll séparé ou en écrivant mon propre cours/méthodes, je savais qu'il devait exister un moyen plus simple. Il s’avère que j’avais raison, car j’ai trouvé comment y parvenir en utilisant seulement deux lignes de code. Cela a fonctionné pour moi.

Heureusement, il s’avère que la méthode .NET Framework Sort () nous aide à cet égard. L'idée est que vous souhaitiez trier les colonnes individuellement, mais l'ordre dans lequel vous les triez est ce qui produira la sortie souhaitée.

Ainsi, à titre d'exemple, j'ai une colonne pour le type de fichier et une colonne pour un nom de fichier. Chaque fois que je veux trier les données selon les types, je veux m'assurer que les noms sont également triés dans chaque type affiché.

OBJECTIF: Le tri par type triera également les noms de fichiers par ordre alphabétique.

Les données:

zxcv.css

testimg3.jpg

asdf.html

testimg2.jpg

testimg1.jpg

Tri des données par nom:

mConflictsDataGridView.Sort(mConflictsDataGridView.Columns[mNameLabel.Index], ListSortDirection.Ascending);

asdf.html

testimg1.jpg

testimg2.jpg

testimg3.jpg

zxcv.css

Comme vous pouvez le constater, cela garantira que les noms seront triés en conséquence, de sorte que lorsque je trie maintenant en fonction des types de fichiers, les deux exigences seront satisfaites.

Tri des données par type de fichier:

mConflictsDataGridView.Sort(mConflictsDataGridView.Columns[mFileExtensionLabel.Index], ListSortDirection.Ascending);

zxcv.css

asdf.html

testimg1.jpg

testimg2.jpg

testimg3.jpg

Voila! C'est trié!

SOLUTION: Dans votre cas, vous voudrez peut-être essayer quelque chose comme ce qui suit, et vous devrez peut-être un peu plus le modifier pour qu'il s'adapte à votre code.

DataGridView1.Sort(DataGridView1.Columns["status"], ListSortDirection.Ascending);
DataGridView1.Sort(DataGridView1.Columns["day"], ListSortDirection.Asscending);

Cela devrait pouvoir afficher vos résultats par jour avec son champ d’état également trié.

5
susieloo_

Vous pouvez utiliser la méthode Sort du DataGridView, mais spécifier un argument qui est une instance d'une classe qui implémente IComparer.

Voici un exemple d'une telle classe:

public class MyTwoColumnComparer : System.Collections.IComparer
{
    private string _SortColumnName1;
    private int _SortOrderMultiplier1;
    private string _SortColumnName2;
    private int _SortOrderMultiplier2;

    public MyTwoColumnComparer(string pSortColumnName1, SortOrder pSortOrder1, string pSortColumnName2, SortOrder pSortOrder2)
    {
        _SortColumnName1 = pSortColumnName1;
        _SortOrderMultiplier1 = (pSortOrder1 == SortOrder.Ascending) ? 1 : -1;
        _SortColumnName2 = pSortColumnName2;
        _SortOrderMultiplier2 = (pSortOrder2 == SortOrder.Ascending) ? 1 : -1;
    }

    public int Compare(object x, object y)
    {
        DataGridViewRow r1 = (DataGridViewRow)x;
        DataGridViewRow r2 = (DataGridViewRow)y;

        int iCompareResult = _SortOrderMultiplier1 * String.Compare(r1.Cells[_SortColumnName1].Value.ToString(), r2.Cells[_SortColumnName1].Value.ToString());
        if (iCompareResult == 0) iCompareResult = _SortOrderMultiplier2 * String.Compare(r1.Cells[_SortColumnName2].Value.ToString(), r2.Cells[_SortColumnName2].Value.ToString());
        return iCompareResult;
    }
}

Maintenant, nous pourrions appeler cela depuis une colonne dont SortMode est 'Programmatic' en un clic de souris:

private void dgvAllMyEmployees_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
    DataGridViewColumn dgvcClicked = dgvAllEmployees.Columns[e.ColumnIndex];
    if (dgvcClicked.SortMode == DataGridViewColumnSortMode.Programmatic)
    {
        _SortOrder = (_SortOrder == SortOrder.Ascending) ? SortOrder.Descending : SortOrder.Ascending;
        MyTwoColumnComparer Sort2C = new MyTwoColumnComparer(dgvcClicked.Name, _SortOrder, "LastName", SortOrder.Ascending);
        dgvAllEmployees.Sort(Sort2C);
    }
}

La variable de niveau de classe _SortOrder aide à garder une trace de l'ordre dans lequel entrer. On peut améliorer ceci davantage pour se souvenir des deux dernières colonnes cliquées et les trier dans l'ordre souhaité.

2
John Kurtz

Vous pouvez essayer this , ou utiliser un tri personnalisé:

private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            if (dataGridView1.Columns[e.ColumnIndex].HeaderText =="day")
            {
               myBindingSource.Sort = "day, hour";
            }
        }
0
pistipanko

La réponse fournie par John Kurtz m'a rapproché. Mais ce que j’ai trouvé, c’est quand j’ai cliqué sur une colonne une fois, elle s’est bien triée par les deux colonnes ... Dans son exemple: dgvcClicked.Name, "LastName". Tellement bon!!

Mais si je cliquais à nouveau sur la colonne, elle ne trierait PAS par la direction opposée. Donc, la colonne est restée bloquée dans Ascending.

Pour surmonter cela, je devais suivre l'ordre de tri manuellement. Commencé avec ce cours:

public class ColumnSorting
{
    public int ColumnIndex { get; set; }
    public ListSortDirection Direction { get; set; }
}

Ensuite, j'ai ajouté cette liste globale:

List<ColumnSorting> _columnSortingList = new List<ColumnSorting>();

Ensuite, dans la méthode qui fait le tri, je voudrais

  1. Vérifiez si l'index de colonne en cours de tri existe déjà dans _columnSortingList. Si non, ajoutez-le.
  2. S'il existe déjà, remplacez l'ordre de tri

Et Bob est ton oncle.

0
Casey Crookston