web-dev-qa-db-de.com

so sortieren Sie eine Datagrid-Ansicht nach 2 Spalten

Wie sortiere ich eine DataGridView nach zwei Spalten (aufsteigend)? Ich habe zwei Spalten: day und status.

Wenn ich nach einer Spalte sortieren muss, mache ich Folgendes:

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

Aber zu zweit?

12
user1112847

Wenn Ihre DataGridView datengebunden ist, können Sie Ihre Datatable -Ansicht sortieren und sie wie folgt neu binden:

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
}

ODER, ohne bindingsource zu verwenden und direkt an DataView zu binden:

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

Fügen Sie eine ausgeblendete Spalte hinzu, die beide kombiniert, und sortieren Sie danach.

6
linkerro

TLDR; Ich habe eine zweizeilige Lösung.

Ich musste das Gleiche tun, aber nachdem ich all diese komplizierten Wege untersucht hatte, um dies zu tun, indem ich entweder eine separate DLL einfügte oder meine eigenen Klassen/Methoden schrieb, wusste ich, dass es einen einfacheren Weg geben musste. Es stellte sich heraus, dass ich recht hatte, weil ich herausgefunden habe, wie dies mit nur zwei Codezeilen erreicht werden kann. Das hat bei mir funktioniert.

Zum Glück stellt sich für uns heraus, dass uns die .NET Framework Sort () -Methode dabei hilft. Die Idee ist, dass Sie die Spalten einzeln sortieren möchten, aber die Reihenfolge, in der Sie sie sortieren, ergibt die gewünschte Ausgabe.

Als Beispiel habe ich eine Spalte für den Dateityp und eine Spalte für den Dateinamen. Wann immer ich die Daten nach den Typen sortieren möchte, möchte ich sicherstellen, dass die Namen auch innerhalb der angezeigten Typen sortiert sind.

ZIEL: Durch Sortieren nach Typ werden die Dateinamen auch alphabetisch sortiert.

Daten:

zxcv.css

testimg3.jpg

asdf.html

testimg2.jpg

testimg1.jpg

Daten nach Namen sortieren:

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

asdf.html

testimg1.jpg

testimg2.jpg

testimg3.jpg

zxcv.css

Wie Sie sehen können, wird dies sicherstellen, dass die Namen entsprechend sortiert werden, so dass, wenn ich jetzt nach den Dateitypen sortiere, beide Anforderungen erfüllt werden.

Sortieren von Daten nach Dateityp:

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

zxcv.css

asdf.html

testimg1.jpg

testimg2.jpg

testimg3.jpg

Voila! Es ist sortiert!

LÖSUNG: In Ihrem Fall möchten Sie möglicherweise etwas wie das Folgende ausprobieren und müssen es möglicherweise noch etwas weiter optimieren, damit es Ihrem eigenen Code entspricht.

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

Dies sollte in der Lage sein, Ihre Ergebnisse tageweise anzuzeigen, wobei das Statusfeld ebenfalls sortiert ist.

5
susieloo_

Sie können die Sort-Methode von DataGridView verwenden, aber ein Argument angeben, das eine Instanz einer Klasse ist, die IComparer implementiert.

Hier ist ein Beispiel für eine solche Klasse:

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

Nun können wir dies von einer Spalte aus aufrufen, deren SortMode bei einem Mausklick 'Programmatic' ist:

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

Die Klassenvariable _SortOrder hilft dabei, die Reihenfolge zu verfolgen, in die eingegangen werden soll. Sie kann noch erweitert werden, um sich die letzten beiden angeklickten Spalten zu merken und sie in der gewünschten Reihenfolge zu sortieren.

2
John Kurtz

Ich benutze diese Lösung, wenn ich mit gebundenen Daten arbeite. Dies funktioniert für unsere Benutzer und zeigt die aktuellen Sortierkriterien an. Alle Sortierungen sind nur in aufsteigender Reihenfolge.

Fügen Sie wie gezeigt ein CheckBox-, ein TextBox-, ein ColumnHeaderMouseClick-Ereignis und Code hinzu. Die CheckBox schaltet die Sichtbarkeit der TextBox um und durch Klicken auf eine Spaltenüberschrift werden die Sortierkriterien zur TextBox hinzugefügt. Um das Textfeld zu löschen, doppelklicken Sie einfach darauf.

        private void FooDataGridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            if(chkMultiSort.Checked == true)
            {
                string columnHeader = FooDataGridView.Columns[e.ColumnIndex].DataPropertyName;
                txtMultiSort.Text += (columnHeader + ", ");
                try
                {
                    FooBindingSource.Sort = txtMultiSort.Text.Remove(txtMultiSort.Text.Length - 2);
                }
                catch
                {
                    MessageBox.Show("Invalid Sort Data", "Information", MessageBoxButtons.OK, MessageBoxIcon.None);
                    txtMultiSort.Text = String.Empty;
                }
            }

        }

        private void ChkMultiSort_CheckedChanged(object sender, EventArgs e)
        {
            if(chkMultiSort.Checked == true)
            {
                txtMultiSort.Visible = true;
            }
            else
            {
                txtMultiSort.Visible = false;
                txtMultiSort.Text = String.Empty;
            }
        }

        private void TxtMultiSort_DoubleClick(object sender, EventArgs e)
        {
            txtMultiSort.Text = String.Empty;
        }

0
Scotjo

Sie können this ausprobieren oder eine benutzerdefinierte Sortierung verwenden:

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

Die Antwort von John Kurtz brachte mich näher. Was ich jedoch fand, war, dass beim ersten Klicken auf eine Spalte tatsächlich die beiden Spalten sortiert wurden ... In seinem Beispiel: dgvcClicked.Name, "LastName". So gut!!

Wenn ich jedoch erneut auf die Spalte klickte, wurde NICHT nach der entgegengesetzten Richtung sortiert. So blieb die Säule in Ascending stecken.

Um dies zu überwinden, musste ich die Sortierreihenfolge manuell verfolgen. Begonnen mit dieser Klasse:

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

Dann habe ich diese Liste mit globalem Geltungsbereich hinzugefügt:

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

Dann würde ich in der Methode, die die Sortierung durchführt,

  1. Überprüfen Sie, ob der zu sortierende Spaltenindex bereits in _columnSortingList vorhanden ist. Wenn nicht, fügen Sie es hinzu.
  2. Wenn es bereits vorhanden ist, tauschen Sie die Sortierreihenfolge aus

Und Bob ist dein Onkel.

0
Casey Crookston