it-swarm.com.de

Wie aktivieren Sie die DataGridView-Sortierung, wenn der Benutzer auf den Spaltenkopf klickt?

Ich habe ein Datagridview auf meinem Formular und fülle es damit aus:

dataGridView1.DataSource = students.Select(s => new { ID = s.StudentId, RUDE = s.RUDE, Nombre = s.Name, Apellidos = s.LastNameFather + " " + s.LastNameMother, Nacido = s.DateOfBirth })
                                   .OrderBy(s => s.Apellidos)
                                   .ToList();

Jetzt verwende ich die s.Apellidos als Standardsortierung, aber ich möchte auch Benutzern die Sortierung beim Klicken auf die Spaltenüberschrift erlauben.

Diese Art wird nicht / die Daten auf irgendeine Weise modifizieren, es ist nur ein Bonus auf der Clientseite, um das Suchen nach Informationen zu erleichtern, wenn der Bildschirm mit ihren Augen gescannt wird.

Danke für die Vorschläge.

66
delete

Setzen Sie alle SortMode-Eigenschaften für alle Spalten (die nach Benutzern sortiert werden können) auf Automatisch 

dataGridView1.DataSource = students.Select(s => new { ID = s.StudentId, RUDE = s.RUDE, Nombre = s.Name, Apellidos = s.LastNameFather + " " + s.LastNameMother, Nacido = s.DateOfBirth })
                                   .OrderBy(s => s.Apellidos)
                                   .ToList();

    foreach(DataGridViewColumn column in dataGridView1.Columns)
    {

        column.SortMode = DataGridViewColumnSortMode.Automatic;
    }

Edit: Da Ihr Datagridview an eine Linq-Abfrage gebunden ist, wird es nicht sortiert. Gehen Sie also durch diesen link , der erläutert, wie Sie eine sortierbare Bindungsliste erstellen und diese dann als Datenquelle an datagridview übergeben.

46
Marshal

Verwenden Sie wie von Niraj vorgeschlagen eine SortableBindingList. Ich habe dies sehr erfolgreich mit der DataGridView verwendet.

Hier ist ein Link zu dem aktualisierten Code, den ich verwendet habe - Präsentation der SortableBindingList - Take Two

Fügen Sie einfach die beiden Quelldateien zu Ihrem Projekt hinzu, und Sie sind im Geschäft.

Quelle ist in SortableBindingList.Zip

26
Tom Bushell

Ihr Datengrid muss an erster Stelle an eine sortierbare Liste gebunden sein.

Erstellen Sie diesen Ereignishandler:

    void MakeColumnsSortable_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
    {
        //Add this as an event on DataBindingComplete
        DataGridView dataGridView = sender as DataGridView;
        if (dataGridView == null)
        {
            var ex = new InvalidOperationException("This event is for a DataGridView type senders only.");
            ex.Data.Add("Sender type", sender.GetType().Name);
            throw ex;
        }

        foreach (DataGridViewColumn column in dataGridView.Columns)
            column.SortMode = DataGridViewColumnSortMode.Automatic;
    }

Und initialisieren Sie das Ereignis jedes Ihrer Datragrids wie folgt:

        dataGridView1.DataBindingComplete += MakeColumnsSortable_DataBindingComplete;
7
Saneesh B

Sie können das DataGridViewColoumnHeaderMouseClick-Ereignis wie folgt verwenden:

Private string order = String.Empty;
private void dgvDepartment_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
    if (order == "d")
{
        order = "a";                
dataGridView1.DataSource = students.Select(s => new { ID = s.StudentId, RUDE = s.RUDE, Nombre = s.Name, Apellidos = s.LastNameFather + " " + s.LastNameMother, Nacido = s.DateOfBirth })   .OrderBy(s => s.Apellidos).ToList();
    }
    else
    {
        order = "d";
        dataGridView1.DataSource = students.Select(s => new { ID = s.StudentId, RUDE = s.RUDE, Nombre = s.Name, Apellidos = s.LastNameFather + " " + s.LastNameMother, Nacido = s.DateOfBirth }.OrderByDescending(s => s.Apellidos)  .ToList()
    }
}
5
thinzar

Sie müssen keine verbindliche Datenquelle erstellen. Wenn Sie die Sortierung für alle Ihre Spalten anwenden möchten, finden Sie hier eine allgemeinere Lösung von mir.

private int _previousIndex;
private bool _sortDirection;

private void gridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
    if (e.ColumnIndex == _previousIndex)
        _sortDirection ^= true; // toggle direction

    gridView.DataSource = SortData(
        (List<MainGridViewModel>)gridReview.DataSource, gridReview.Columns[e.ColumnIndex].Name, _sortDirection);

    _previousIndex = e.ColumnIndex;
}

public List<MainGridViewModel> SortData(List<MainGridViewModel> list, string column, bool ascending)
{
    return ascending ? 
        list.OrderBy(_ => _.GetType().GetProperty(column).GetValue(_)).ToList() :
        list.OrderByDescending(_ => _.GetType().GetProperty(column).GetValue(_)).ToList();
}

Stellen Sie sicher, dass Sie Ihr Datenraster für das Ereignis ColumnHeaderMouseClick abonnieren. Wenn der Benutzer auf die Spalte klickt, wird sie nach absteigend sortiert. Wenn erneut auf dieselbe Spaltenüberschrift geklickt wird, erfolgt die Sortierung nach aufsteigend.

4
0014


Es gibt eine einfache Lösung, wenn Entity Framework (Version 6 in diesem Fall) verwendet wird. Ich bin nicht sicher, aber es scheint, dass die ObservableCollectionExtensions.ToBindingList<T>-Methode die Implementierung der sortable binding-Liste zurückgibt. Ich habe keinen Quellcode gefunden, um diese Annahme zu bestätigen, aber das Objekt, das von dieser Methode zurückgegeben wird, funktioniert mit DataGridView sehr gut, besonders wenn Spalten durch Anklicken der Kopfzeilen sortiert werden.

Der Code ist sehr einfach und basiert nur auf .NET-Klassen und Entity-Framework-Klassen:

using System.Data.Entity;

IEnumerable<Item> items = MethodCreatingItems();

var observableItems = new System.Collections.ObjectModel.ObservableCollection<Item>(items);
System.ComponentModel.BindingList<Item> source = observableItems.ToBindingList();

MyDataGridView.DataSource = source;
3
Adam Matecki

Eine weitere Möglichkeit hierzu ist die Verwendung der Bibliothek "System.Linq.Dynamic". Sie können diese Bibliothek von Nuget erhalten. Keine benutzerdefinierten Implementierungen oder sortierbaren Listen nötig :)

using System.Linq.Dynamic;
private bool sortAscending = false;

private void dataGridView_ColumnHeaderMouseClick ( object sender, DataGridViewCellMouseEventArgs e )
{
    if ( sortAscending )
        dataGridView.DataSource = list.OrderBy ( dataGridView.Columns [ e.ColumnIndex ].DataPropertyName ).ToList ( );
    else
        dataGridView.DataSource = list.OrderBy ( dataGridView.Columns [ e.ColumnIndex ].DataPropertyName ).Reverse ( ).ToList ( );
    sortAscending = !sortAscending;
}

KISS: Mach es einfach, dumm

Weg A: Implementieren Sie eine eigene SortableBindingList - Klasse, wenn Sie DataBinding und sorting verwenden möchten.

Weg B: Eine Sortierung von List <string> funktioniert ebenfalls, funktioniert jedoch nicht mit DataBinding.

2
hfrmobile

Wenn du eine Fehlermeldung bekommst

Eine nicht behandelte Ausnahme des Typs 'System.NullReferenceException' in System.Windows.Forms.dll aufgetreten

wenn Sie mit SortableBindingList arbeiten, verwendet Ihr Code wahrscheinlich einige Schleifen über DataGridView-Zeilen und versucht auch, auf die leere letzte Zeile zuzugreifen! (BindingSource = null)

Wenn Sie dem Benutzer nicht erlauben müssen, neue Zeilen direkt in DataGridView hinzuzufügen, können Sie das Problem leicht mit dieser Codezeile beheben:

InitializeComponent();
m_dataGridView.AllowUserToAddRows = false; // after components initialized
...
1
leon22

Ich empfehle die Verwendung einer DataTable.DefaultView als DataSource. Dann die Zeile darunter.

foreach (DataGridViewColumn column in gridview.Columns)
    {
       column.SortMode = DataGridViewColumnSortMode.Automatic;
    }

Danach verwaltet das Gridview selbst die Sortierung (Aufsteigend oder Absteigend wird unterstützt).

1
Milad
  1. Erstellen Sie eine Klasse, die alle benötigten Eigenschaften enthält, und füllen Sie sie im Konstruktor auf

    class Student
    {
        int _StudentId;
        public int StudentId {get;}
        string _Name;
        public string Name {get;}
        ...
    
        public Student(int studentId, string name ...)
        { _StudentId = studentId; _Name = name; ... }
    }
    
  2. Erstellen Sie eine IComparer-Klasse <Student>, um sortieren zu können

    class StudentSorter : IComparer<Student>
    {
        public enum SField {StudentId, Name ... }
        SField _sField; SortOrder _sortOrder;
    
        public StudentSorder(SField field, SortOrder order)
        { _sField = field; _sortOrder = order;}
    
        public int Compare(Student x, Student y)
        {
            if (_SortOrder == SortOrder.Descending)
            {
                Student tmp = x;
                x = y;
                y = tmp;
            }
    
            if (x == null || y == null)
                return 0;
    
            int result = 0;
            switch (_sField)
            {
                case SField.StudentId:
                    result = x.StudentId.CompareTo(y.StudentId);
                    break;
                case SField.Name:
                    result = x.Name.CompareTo(y.Name);
                    break;
                    ...
            }
    
            return result;
        }
    }
    
  3. Innerhalb des Formulars mit dem Datagrid hinzufügen

    ListDictionary sortOrderLD = new ListDictionary(); //if less than 10 columns
    private SortOrder SetOrderDirection(string column)
    {
        if (sortOrderLD.Contains(column))
        {
            sortOrderLD[column] = (SortOrder)sortOrderLD[column] == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending;
        }
        else
        {
            sortOrderLD.Add(column, SortOrder.Ascending);
        }
    
        return (SortOrder)sortOrderLD[column];
    }
    
  4. In datagridview_ColumnHeaderMouseClick-Ereignisbehandlungsroutine tun Sie so etwas

    private void dgv_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
    {
        StudentSorter sorter = null;
        string column = dGV.Columns[e.ColumnIndex].DataPropertyName; //Use column name if you set it
        if (column == "StudentId")
        {
            sorter = new StudentSorter(StudentSorter.SField.StudentId, SetOrderDirection(column));
        }
        else if (column == "Name")
        {
            sorter = new StudentSorter(StudentSorter.SField.Name, SetOrderDirection(column));
        }
    
        ...
    
        List<Student> lstFD = datagridview.DataSource as List<Student>;
        lstFD.Sort(sorter);
        datagridview.DataSource = lstFD;
        datagridview.Refresh();
    }
    

Hoffe das hilft

1
Albert

Ich habe ein BindingList <> -Objekt als Datenquelle für dataGridView.

BindingList x1;
x1 = new BindingList<sourceObject>();
BindingSource bsx1 = new BindingSource();
bsx1.DataSource = x1;
dataGridView1.DataSource = bsx1;

Wenn ich auf die Spaltenüberschrift geklickt habe, findet keine Sortierung statt. Ich habe die Antwort von SortableBindingList von Tom Bushell verwendet. Nachdem zwei Quelldateien in mein Projekt eingefügt wurden

  1. SortableBindingList.cs
  2. PropertyComparer.cs

Dann wird diese Änderung an meinem Code vorgenommen:

Be.Timvw.Framework.ComponentModel.SortableBindingList x1;                       // 1
x1 = new Be.Timvw.Framework.ComponentModel.SortableBindingList<sourceObject>(); // 2
BindingSource bsx1 = new BindingSource();
bsx1.DataSource = x1;
dataGridView1.DataSource = bsx1;

Nach diesen Änderungen habe ich mein Programm weiterentwickelt. Ich kann jetzt durch Klicken auf die Spaltenüberschriften sortieren. Nur zwei Zeilen müssen geändert werden. Sie werden im Code-Snippet oben durch nachfolgende Kommentare hervorgehoben. 

0
user3674642

In meinem Fall bestand das Problem darin, dass ich meine DataSource als object gesetzt hatte, weshalb sie nicht sortiert wurde. Nach dem Wechsel von object zu DataTable funktionierte es ohne Code-Komplement. 

0

Für den Fall, dass jemand noch danach sucht, habe ich es bei VS 2008 C # gemacht.

Fügen Sie im Event ColumnHeaderMouseClick eine Datenbindung für die Rasteransicht hinzu und senden Sie die Reihenfolge nach Feld wie einen Parameter. Sie können das angeklickte Feld wie folgt erhalten:

dgView.Columns[e.ColumnIndex].Name

In meinem Fall ähneln die Kopfzeilen den Namen der Ansichtsfelder.

0
Hugo Bazan

fügen Sie diese Zeile in Ihr Windows-Formular ein (beim Laden oder besser in einer öffentlichen Methode wie "binddata"): 

//
// bind the data and make the grid sortable 
//
this.datagridview1.MakeSortable( myenumerablecollection ); 

Fügen Sie diesen Code in eine Datei namens DataGridViewExtensions.cs (oder ähnliches) ein. 

// MakeSortable extension. 
// this will make any enumerable collection sortable on a datagrid view.  

//
// BEGIN MAKESORTABLE - Mark A. Lloyd
//
// Enables sort on all cols of a DatagridView 

//



    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using System.Windows.Forms;

    public static class DataGridViewExtensions
    {
    public static void MakeSortable<T>(
        this DataGridView dataGridView, 
        IEnumerable<T> dataSource,
        SortOrder defaultSort = SortOrder.Ascending, 
        SortOrder initialSort = SortOrder.None)
    {
        var sortProviderDictionary = new Dictionary<int, Func<SortOrder, IEnumerable<T>>>();
        var previousSortOrderDictionary = new Dictionary<int, SortOrder>();
        var itemType = typeof(T);
        dataGridView.DataSource = dataSource;
        foreach (DataGridViewColumn c in dataGridView.Columns)
        {
            object Provider(T info) => itemType.GetProperty(c.Name)?.GetValue(info);
            sortProviderDictionary[c.Index] = so => so != defaultSort ? 
                dataSource.OrderByDescending<T, object>(Provider) : 
                dataSource.OrderBy<T,object>(Provider);
            previousSortOrderDictionary[c.Index] = initialSort;
        }

        async Task DoSort(int index)
        {

            switch (previousSortOrderDictionary[index])
            {
                case SortOrder.Ascending:
                    previousSortOrderDictionary[index] = SortOrder.Descending;
                    break;
                case SortOrder.None:
                case SortOrder.Descending:
                    previousSortOrderDictionary[index] = SortOrder.Ascending;
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }

            IEnumerable<T> sorted = null;
            dataGridView.Cursor = Cursors.WaitCursor;
            dataGridView.Enabled = false;
            await Task.Run(() => sorted = sortProviderDictionary[index](previousSortOrderDictionary[index]).ToList());
            dataGridView.DataSource = sorted;
            dataGridView.Enabled = true;
            dataGridView.Cursor = Cursors.Default;

        }

        dataGridView.ColumnHeaderMouseClick+= (object sender, DataGridViewCellMouseEventArgs e) => DoSort(index: e.ColumnIndex);
    }
}
0
Mark Lloyd