2009-09-04 2 views
17

Ich verwende ein Windows Forms DataGridView, um eine generische Liste von MyObject Objekte anzuzeigen.C# DataGridView Sortierung mit Generic List als zugrunde liegende Quelle

Zunächst einmal wickeln ich diese Sammlung in eine BindingSource Sammlung, dann:

dataGridView.DataSource = myBindingSource; 

Was will ich tun erlauben dem Benutzer die Spalten zu sortieren, indem Sie auf die Überschrift der Spalte clickin eine konkrete Eigenschaft darstellt in MeinObjekt.

Ich habe einige Artikel gelesen, die ich vor dem Binden sortieren sollte. Aber es hilft mir nicht, wenn ich die Kolumnen in Echtzeit sortieren will, wenn es bereits gebunden ist.

Die Frage ist, was genau ich tun muss, so Ich konnte die Sortierpfeile in Datagridview sehen und ich jede Spalte sortieren kann?

+1

Siehe http://stackoverflow.com/questions/3770857/how-do-i-implement-automatic-sorting-of-datagridview. Es ist so einfach wie 'dataGridView.DataSource = new BindingListView (myObjects.ToList())' mit der Bibliothek unter http://sourceforge.net/projects/blw/. – Pat

Antwort

2

Meine Lösung ist dies:

ich mit myBindingSource arbeiten an meinem eigenen, ich Sortieren, Gruppieren ..whatever in einem separaten Thread. Dann bin ich einfach binden das Ergebnis an die DataGridView.

myDataGridView.DataSource = bindingSource; 

Zu diesem Zweck ich alle Spalten gefassten haben 'Programatically' sortiert (in Designer) werden dann manuell hinzufügen ich den Pfeil (Aufstiegs-/Abstiegs) von

cell.SortGlyphDirection = ... ; 

in Code hinter Einstellung .

0

sehen diese artice

http://msdn.microsoft.com/en-us/library/0868ft3z.aspx

durch i Lektüre dieses „Dieses Verfahren sah den Inhalt der Datagridview sortiert durch Werte in der angegebenen Spalte verglichen wird. Standardmäßig wird der Sortiervorgang die Methode Vergleichen Sie verwenden Vergleichen von Zellenpaaren in der Spalte mithilfe der DataGridViewCell .. ::. Value-Eigenschaft. "

Mit besten Grüßen, Iordan

30

kompletter Code, um die Spalte von Datagridview, deren Datenquelle zu sortieren ist eine generische Liste

//----------------------------------------------------------------------------------------- 
//In the form - In constructor or form load, populate the grid. 
//-------------------------------------------------------------------------------------------- 

    List<student> students; 

    private void PopulateList() 
    { 
     student std1 = new student("sss", 15, "Female"); 
     student std2 = new student("ddd", 12, "Male"); 
     student std3 = new student("zzz", 16, "Male"); 
     student std4 = new student("qqq", 14, "Female"); 
     student std5 = new student("aaa", 11, "Male"); 
     student std6 = new student("lll", 13, "Female"); 

     students = new List<student>(); 
     students.Add(std1); 
     students.Add(std2); 
     students.Add(std3); 
     students.Add(std4); 
     students.Add(std5); 
     students.Add(std6); 

     dataGridView1.DataSource = students; 
    } 


//--------------------------------------------------------------------------------------------- 
//Comparer class to perform sorting based on column name and sort order 
//--------------------------------------------------------------------------------------------- 


class StudentComparer : IComparer<Student> 
{ 
    string memberName = string.Empty; // specifies the member name to be sorted 
    SortOrder sortOrder = SortOrder.None; // Specifies the SortOrder. 

    /// <summary> 
    /// constructor to set the sort column and sort order. 
    /// </summary> 
    /// <param name="strMemberName"></param> 
    /// <param name="sortingOrder"></param> 
    public StudentComparer(string strMemberName, SortOrder sortingOrder) 
    { 
     memberName = strMemberName; 
     sortOrder = sortingOrder; 
    } 

    /// <summary> 
    /// Compares two Students based on member name and sort order 
    /// and return the result. 
    /// </summary> 
    /// <param name="Student1"></param> 
    /// <param name="Student2"></param> 
    /// <returns></returns> 
    public int Compare(Student Student1, Student Student2) 
    { 
     int returnValue = 1; 
     switch (memberName) 
     { 
      case "Name" : 
       if (sortOrder == SortOrder.Ascending) 
       { 
        returnValue = Student1.Name.CompareTo(Student2.Name); 
       } 
       else 
       { 
        returnValue = Student2.Name.CompareTo(Student1.Name); 
       } 

       break; 
      case "Sex": 
       if (sortOrder == SortOrder.Ascending) 
       { 
        returnValue = Student1.Sex.CompareTo(Student2.Sex); 
       } 
       else 
       { 
        returnValue = Student2.Sex.CompareTo(Student1.Sex); 
       } 
       break; 
      default: 
       if (sortOrder == SortOrder.Ascending) 
       { 
        returnValue = Student1.Name.CompareTo(Student2.Name); 
       } 
       else 
       { 
        returnValue = Student2.Name.CompareTo(Student1.StudentId); 
       } 
       break; 
     } 
     return returnValue; 
    } 
} 



//--------------------------------------------------------------------------------------------- 
// Performing sort on click on Column Header 
//--------------------------------------------------------------------------------------------- 

    private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) 
    { 
     //get the current column details 
     string strColumnName = dataGridView1.Columns[e.ColumnIndex].Name; 
     SortOrder strSortOrder = getSortOrder(e.ColumnIndex); 

     students.Sort(new StudentComparer(strColumnName, strSortOrder)); 
     dataGridView1.DataSource = null; 
     dataGridView1.DataSource = students; 
     customizeDataGridView(); 
     dataGridView1.Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection = strSortOrder; 
    } 

    /// <summary> 
    /// Get the current sort order of the column and return it 
    /// set the new SortOrder to the columns. 
    /// </summary> 
    /// <param name="columnIndex"></param> 
    /// <returns>SortOrder of the current column</returns> 
    private SortOrder getSortOrder(int columnIndex) 
    { 
     if (dataGridView1.Columns[columnIndex].HeaderCell.SortGlyphDirection == SortOrder.None || 
      dataGridView1.Columns[columnIndex].HeaderCell.SortGlyphDirection == SortOrder.Descending) 
     { 
      dataGridView1.Columns[columnIndex].HeaderCell.SortGlyphDirection = SortOrder.Ascending; 
      return SortOrder.Ascending; 
     } 
     else 
     { 
      dataGridView1.Columns[columnIndex].HeaderCell.SortGlyphDirection = SortOrder.Descending; 
      return SortOrder.Descending; 
     } 
    } 
+0

Tolle Lösung, vielen Dank! Ich habe mir die Zeit genommen und es ein wenig verbessert. –

6

Ich finde es schwer zu glauben, ist das Gitter nicht grundlegende Sortierung aus der Box zur Verfügung stellen, kein Code erforderlich. Immerhin ist es ziemlich albern, ein Header-Click-Ereignis behandeln zu müssen und DataGridView.Sort aufzurufen, das die Spalte angibt (bestimmt durch das angeklickte, vom Grid verfolgte) und die Sortierrichtung (bestimmt durch den aktuellen Sortierzustand, verfolgt durch das Raster)).

Warum gibt es nicht einfach eine SortMode- oder eine AllowUserToSort-Eigenschaft, die standardmäßig genau dasselbe tut?

Ich habe mein Gitter an eine Liste gebunden und die Eigenschaften, denen ich Spalten zugeordnet habe, sind alle grundlegenden Typen wie string, int, DateTime und so weiter. Alle sind IComparable. Warum sollte ich also nur eine Zeile Code schreiben müssen?Besonders wenn man bedenkt, dass die Dokumentation lautet:

Standardmäßig können Benutzer die Daten in ein Steuerelement Datagridview sortieren kann durch Anklicken des Header eines Textfeld Spalte.

MSDN

Das ist das Framework 3.0 doc ist, und ich bin 3.5 Targeting, aber "andere Versionen" alle Versionen von Visual Studio verweisen, nicht Versionen des Frameworks. Was um alles in der Welt geht hier Microsoft?!?

+0

BTW meine Spalten sind alle vom Typ DataGridViewTextBoxColumn - das ist vermutlich, was MS bedeutet, wenn Sie "eine Textfeld-Spalte" sagen. –

+0

Es gibt einen SortMode, aber scheinbar nichts! – ProfK

0

Hier ist eine einfachere Lösung zum Sortieren nach Spalten mit Reflection und Linq. dataGridView1 Datasource wird auf compareList gesetzt, die erklären, wie:

private List<CompareInfo> compareList; 


    private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) 
    { 
     string strColumnName = dataGridView1.Columns[e.ColumnIndex].Name; 
     SortOrder strSortOrder = getSortOrder(e.ColumnIndex); 

     if (strSortOrder == SortOrder.Ascending) 
     { 
      compareList = compareList.OrderBy(x => typeof(CompareInfo).GetProperty(strColumnName).GetValue(x, null)).ToList(); 
     } 
     else 
     { 
      compareList = compareList.OrderByDescending(x => typeof(CompareInfo).GetProperty(strColumnName).GetValue(x, null)).ToList(); 
     } 
     dataGridView1.DataSource = compareList; 
     dataGridView1.Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection = strSortOrder; 
    } 

    private SortOrder getSortOrder(int columnIndex) 
    { 
     if (dataGridView1.Columns[columnIndex].HeaderCell.SortGlyphDirection == SortOrder.None || 
      dataGridView1.Columns[columnIndex].HeaderCell.SortGlyphDirection == SortOrder.Descending) 
     { 
      dataGridView1.Columns[columnIndex].HeaderCell.SortGlyphDirection = SortOrder.Ascending; 
      return SortOrder.Ascending; 
     } 
     else 
     { 
      dataGridView1.Columns[columnIndex].HeaderCell.SortGlyphDirection = SortOrder.Descending; 
      return SortOrder.Descending; 
     } 
    } 


public class CompareInfo 
{ 
    public string FileName { get; set; } 

    public string UAT_Folder { get; set; } 

    public string UAT_Path 
    { 
     get { return UAT_Folder + FileName; } 
    } 

    public string PROD_Folder { get; set; } 

    public string PROD_Path 
    { 
     get { return PROD_Folder + FileName; } 
    } 
} 
+0

Ich habe diese Lösung leicht modifiziert, um schneller Ergebnisse zu erzielen. Ich habe DataPropertyName anstelle von Name für den strColumnName verwendet und meine Vergleichsliste innerhalb des click -Ereignisses am oberen Rand gewürfelt: var compareList = (dataGridView1.DataSource als Liste ); Das war gut genug für meine Bedürfnisse für eine einmalige App. – archangel76

0

Eine weitere Möglichkeit, die Sortierung Problem mit Datagridview zu lösen, wenn Liste verbindlich sind, wenn Sie nicht mit großer Datenmenge zu tun haben, dann können Sie wahrscheinlich die konvertieren versuchen, Auf DataTable auflisten und dann die resultierende DataTable an die BindingSource/DataGridView binden.

Dies würde die Notwendigkeit für eine benutzerdefinierte Implementierung von IComparer. In meinem Fall hatte ich es mit einer kleineren Liste zu tun, aber es gab mehr Felder, die angezeigt werden konnten. Die Implementierung von IComparer bedeutete also, zu viel Kesselblechcode zu schreiben.

prüfen diese für terse Weg, um die Liste zu Datatable Umwandlung: https://stackoverflow.com/a/34062898/4534493