2009-09-04 13 views
17

Używam Windows Forms DataGridView do wyświetlania ogólnej listy obiektów MyObject.C# Sortowanie DataGridView z ogólną listą jako źródłem

Przede wszystkim zawijać tej kolekcji w BindingSource Collection, a następnie:

dataGridView.DataSource = myBindingSource; 

Co chcę zrobić, to pozwolić użytkownikowi na sortowanie przez clickin na nagłówku kolumny reprezentujący konkretny obiekt w MyObject.

Czytałem artykuły, które powinienem sortować przed wiązaniem. Ale nie pomaga mi to, gdy chcę sortować kolumny w czasie rzeczywistym, gdy mówię, że są już powiązane.

Chodzi o to, co dokładnie muszę zrobić, więc Widziałem Sortowanie strzały w DataGridView i mogę posortować każda kolumna?

+1

Zobacz http://stackoverflow.com/questions/3770857/how-do-i-implement-automatic-sorting-of-datagridview. Jest to tak proste jak 'dataGridView.DataSource = new BindingListView (myObjects.ToList())' z biblioteką na stronie http://sourceforge.net/projects/blw/. – Pat

Odpowiedz

2

moje rozwiązanie to:

pracuję z myBindingSource na własną rękę, ja sortowanie, grupowanie ..whatever w osobnym wątku. Następnie po prostu wiążę wynik z DataGridView.

myDataGridView.DataSource = bindingSource; 

W tym celu mam setted wszystkie kolumny mają być sortowane 'Programatically' (w projektanta) Potem ręcznie dodać strzałkę (rosnąco/malejąco) ustawiając

cell.SortGlyphDirection = ... ; 

w kodzie tyłu .

0

zobaczyć ten artice

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

czytając to widziałem to „Ta metoda sortuje zawartość DataGridView przez porównanie wartości w określonej kolumnie. Domyślnie operacja sortowania użyje Porównaj metody porównać pary komórek w kolumnie za pomocą właściwości DataGridViewCell .. ::. Value. "

Pozdrawiam, Iordan

30

Kompletny kod aby posortować kolumnę DataGridView którego źródła danych jest ogólną listę

//----------------------------------------------------------------------------------------- 
//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

Świetne rozwiązanie, dziękuję bardzo! Zrobiłem trochę czasu i trochę go poprawiłem. –

6

trudno mi uwierzyć, siatka nie zapewnia podstawową sortowania po wyjęciu z pudełka, bez kodu potrzebne. W końcu całkiem głupio jest obsłużyć zdarzenie click nagłówka i wywołać funkcję DataGridView.Sort wskazującą kolumnę (określoną przez kliknięcie, śledzone przez siatkę) i kierunek sortowania (określony przez bieżący stan sortowania, śledzony przez siatkę).

Dlaczego nie ma po prostu właściwości SortMode lub AllowUserToSort, która domyślnie wykonuje dokładnie to samo?

Połączyłem moją siatkę z listą, a właściwości, które zamapowałem, są typami podstawowymi, takimi jak string, int, DateTime i tak dalej. Wszystkie z nich są porównywalne. Dlaczego więc, na litość, powinienem napisać nawet jedną linię kodu?Zwłaszcza biorąc pod uwagę, że dokumentacja brzmi:

Domyślnie użytkownicy mogą sortować dane w formantu DataGridView, klikając nagłówek kolumny polu tekstowym .

MSDN

To Framework 3.0 doc, a ja kierowania 3.5, ale "inne wersje" odnoszą się do wersji Visual Studio, a nie wersje ram. Co tu, u licha, dzieje się tutaj Microsoft?!?

+0

BTW moje kolumny są wszystkie typu DataGridViewTextBoxColumn - co prawdopodobnie jest, co MS oznacza, mówiąc "kolumna pole tekstowe". –

+0

Istnieje tryb SortMode, ale wygląda na to, że nic nie robi! – ProfK

0

Oto prostsze rozwiązanie do sortowania według kolumn za pomocą Reflection i Linq. DataSource dataGridView1 jest ustawiony na compareList która jest zadeklarowana jako:

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

Zmodyfikowałem to rozwiązanie, aby uzyskać szybszy rezultat. Użyłem DataPropertyName zamiast Name dla parametru strColumnName, a ja przesyłaję moją listę porównawczą wewnątrz zdarzenia kliknięcia u góry: var compareList = (dataGridView1.DataSource jako List ); To było wystarczająco dobre dla moich potrzeb na jednorazową aplikację. – archangel76

0

Inną opcją, aby rozwiązać ten problem sortowania z DataGridView podczas wiązania na liście jest, jeśli nie mamy do czynienia z ogromnymi danych przedstawionych następnie prawdopodobnie można próbować przekonwertować Wyświetl listę DataTable, a następnie powiązaj wynikową tabelę danych ze źródłem BindingSource/DataGridView.

To byłaby potrzeba niestandardowej implementacji programu IComparer. W moim przypadku miałem do czynienia z mniejszą listą, ale było więcej pól do wyświetlenia. Wdrożenie programu IComparer oznaczało pisanie za dużo kodu płyty kotła.

Sprawdź to dla zwięzły sposób konwersji listy do DataTable: https://stackoverflow.com/a/34062898/4534493

Powiązane problemy