How to enable DataGridView sorting when user clicks on the column header?

前端 未结 15 937
误落风尘
误落风尘 2020-12-02 15:28

I have a datagridview on my form and I populate it with this:

dataGridView1.DataSource = students.Select(s => new { ID = s.StudentId, RUDE = s.RUDE, Nombr         


        
相关标签:
15条回答
  • 2020-12-02 15:51
    1. Create a class which contains all properties you need, and populate them in the constructor

      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. Create an IComparer < Student > class, to be able to sort

      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. Within the form containing the datagrid add

      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. Within datagridview_ColumnHeaderMouseClick event handler do something like this

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

    Hope this helps

    0 讨论(0)
  • 2020-12-02 15:54

    You don't need to create a binding datasource. If you want to apply sorting for all of your columns, here is a more generic solution of mine;

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

    Make sure you subscribe your data grid to the event ColumnHeaderMouseClick. When the user clicks on the column it will sort by descending. If the same column header is clicked again, sorting will be applied by ascending.

    0 讨论(0)
  • 2020-12-02 15:58

    KISS : Keep it simple, stupid

    Way A: Implement an own SortableBindingList class when like to use DataBinding and sorting.

    Way B: Use a List<string> sorting works also but does not work with DataBinding.

    0 讨论(0)
提交回复
热议问题