Ich habe eine Datagrid-Ansicht in meinem Formular und fülle sie folgendermaßen 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, möchte aber auch Benutzern das Sortieren erlauben, wenn sie auf die Spaltenüberschrift klicken.
Diese Art wird nicht die Daten in irgendeiner Art und Weise ändern, es ist nur ein Client - Seite Bonus für eine einfachere Suche nach Informationen zu ermöglichen , wenn der Bildschirm mit ihren Augen scannen.
Danke für die Vorschläge.
Antworten:
Setzen Sie alle SortMode-Eigenschaften aller Spalten (die von 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; }
Bearbeiten: Da Ihre Datagrid-Ansicht an eine Linq-Abfrage gebunden ist, wird sie nicht sortiert. Gehen Sie also bitte über diesen Link, der erklärt, wie Sie eine sortierbare Bindungsliste erstellen und diese dann als Datenquelle an datagridview weiterleiten.
quelle
foreach
könnten einfacher sein:foreach(DataGridViewColumn column in dataGridView1.Columns) column.SortMode = DataGridViewColumnSortMode.Automatic;
Verwenden Sie, wie Niraj vorgeschlagen hat, eine SortableBindingList . Ich habe dies sehr erfolgreich mit dem DataGridView verwendet.
Hier ist ein Link zu dem aktualisierten Code, den ich verwendet habe - Präsentieren der SortableBindingList - Take Two
Fügen Sie einfach die beiden Quelldateien zu Ihrem Projekt hinzu, und Sie sind im Geschäft.
Die Quelle befindet sich in SortableBindingList.zip
quelle
Eine weitere Möglichkeit hierfür ist die Verwendung der Bibliothek "System.Linq.Dynamic". Sie können diese Bibliothek von Nuget erhalten . Keine benutzerdefinierten Implementierungen oder sortierbaren Listen erforderlich :)
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; }
quelle
OrderByDescending
für denelse
Fall wäre besser.dataGridView.ColumnHeaderMouseClick += dataGridView_ColumnHeaderMouseClick;
und dies für BindingList zu implementieren, das jedes Mal aktualisiert wird, wenn Daten eingehen ... Sie müssen den Code ändern ...dataGridView.DataSource = new BindingList<Data>(dataList.OrderBy(dataGridView.Columns[e.ColumnIndex].DataPropertyName).ToList());
Ihr Datenraster muss zunächst 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:
quelle
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 abonnieren
ColumnHeaderMouseClick
. Wenn der Benutzer auf die Spalte klickt, wird sie nach absteigend sortiert. Wenn dieselbe Spaltenüberschrift erneut angeklickt wird, wird die Sortierung durch Aufsteigen angewendet.quelle
Sie können das DataGridViewColoumnHeaderMouseClick-Ereignis folgendermaßen 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() } }
quelle
Bei Verwendung von Entity Framework (in diesem Fall Version 6) gibt es eine ganz einfache Lösung. Ich bin nicht sicher, aber es scheint, dass die
ObservableCollectionExtensions.ToBindingList<T>
Methode die Implementierung einer sortierbaren Bindungsliste zurückgibt . Ich habe keinen Quellcode gefunden, um diese Annahme zu bestätigen, aber das von dieser Methode zurückgegebene Objekt funktioniertDataGridView
sehr gut, insbesondere beim Sortieren von Spalten durch Klicken auf die Überschriften.Der Code ist sehr einfach und basiert nur auf .net- 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;
quelle
KISS: Halte es einfach, dumm
Weg A: Implementieren Sie eine eigene SortableBindingList- Klasse, wenn Sie DataBinding und Sorting verwenden möchten .
Weg B: Verwenden Sie eine List <String> -Sortierung funktioniert auch, aber nicht mit DataBinding .
quelle
Wenn Sie eine Fehlermeldung wie erhalten
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, kann das Problem mit dieser Codezeile leicht behoben werden:
InitializeComponent(); m_dataGridView.AllowUserToAddRows = false; // after components initialized ...
quelle
Erstellen Sie eine Klasse, die alle benötigten Eigenschaften enthält, und füllen Sie sie im Konstruktor aus
class Student { int _StudentId; public int StudentId {get;} string _Name; public string Name {get;} ... public Student(int studentId, string name ...) { _StudentId = studentId; _Name = name; ... } }
Erstellen Sie eine IComparer <Student> -Klasse, 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; } }
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]; }
Führen Sie in datagridview_ColumnHeaderMouseClick den Ereignishandler so etwas aus
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
quelle
Ich schlage vor, eine DataTable.DefaultView als DataSource zu verwenden. Dann die Zeile unten.
foreach (DataGridViewColumn column in gridview.Columns) { column.SortMode = DataGridViewColumnSortMode.Automatic; }
Danach verwaltet die Rasteransicht selbst die Sortierung (Aufsteigend oder Absteigend wird unterstützt.)
quelle
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 mit dem Namen DataGridViewExtensions.cs (oder ähnlich) 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); } }
quelle
Nur für den Fall, dass noch jemand danach sucht, habe ich es auf VS 2008 C # gemacht.
Fügen Sie im Ereignis ColumnHeaderMouseClick eine Datenbindung für die Rasteransicht hinzu und senden Sie die Reihenfolge nach Feld wie ein Parameter. Sie können das angeklickte Feld wie folgt erhalten:
In meinem Fall ähneln die Namen der Header den Namen der Anzeigefelder.
quelle
Ich habe ein BindingList <> -Objekt als Datenquelle an dataGridView gebunden.
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 SortableBindingList-Antwort von Tom Bushell verwendet. Nachdem ich zwei Quelldateien in mein Projekt aufgenommen habe
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 ein Build für mein Programm durchgeführt. Ich kann jetzt sortieren, indem ich auf die Spaltenüberschriften klicke. Es müssen nur zwei Zeilen geändert werden. Sie werden im obigen Codeausschnitt durch nachfolgende Kommentare hervorgehoben.
quelle
In meinem Fall war das Problem, dass ich meine
DataSource
als festgelegt hatteobject
, weshalb sie nicht sortiert wurde. Nach dem Wechsel vonobject
zu aDataTable
funktionierte es gut ohne Code-Ergänzung.quelle