Tengo un datagridview en mi formulario y me rellenar con esto:

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

Ahora, yo uso la s.Apellidos como el criterio de ordenación predeterminado, pero también me gustaría que los usuarios puedan ordenar al hacer clic en el encabezado de la columna.

Este tipo de no modificar los datos de cualquier manera, es sólo un cliente de bono de lado para facilitar la búsqueda de información cuando se escanea la pantalla con sus ojos.

Gracias por las sugerencias.

InformationsquelleAutor | 2011-04-05

15 Comentarios

  1. 48

    Conjunto de todos los de la columna (que puede ser ordenable por los usuarios) SortMode propiedad Automático

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

    Edición: Como tu datagridview enlazado con una consulta linq, no va a ser ordenados. Así que por favor vaya a través de este enlace que explica cómo crear un ordenable enlace de la lista y, a continuación, se alimentan como origen de datos para datagridview.

    • Ya quiero que todas las columnas se pueden ordenar, es allí una manera a través de programación iterar a través de cada columna y establecer esta propiedad?
    • Obtengo un error del compilador. Traté de cambiar su respuesta a la columna.Nombre pero no parece modificar la clasificación de alguna manera.
    • Puede usted decir qué error hacer u recibir ?
    • Edita tu respuesta. Antes era sólo ‘columna’ y se dispara un error del compilador. He cambiado a la columna.Nombre para hacer el trabajo, entonces, cambió su respuesta. Sin embargo, esto todavía no me permiten ordenar la información.
    • Así que, si he entendido bien, ahora usted no recibe ningún tipo de error, pero todavía las columnas no se pueden clasificar.
    • Correcto. Hago clic en el encabezado de columna y las filas no el fin en sí mismos.
    • Por favor, consulte este enlace y también conocer en la edición de una parte de la respuesta
    • Por cierto, su foreach podría ser más simple: foreach(DataGridViewColumn column in dataGridView1.Columns) column.SortMode = DataGridViewColumnSortMode.Automatic;
    • Esta respuesta me ayudó a encontrar una solución para mi problema. Aquí está mi respuesta: stackoverflow.com/a/43997006/6186647

  2. 26

    Como Niraj sugerido, el uso de un SortableBindingList. La he usado con mucho éxito con el DataGridView.

    Aquí hay un enlace a la versión actualizada del código que he usado – La presentación de la SortableBindingList – Tomar Dos

    Acaba de agregar los dos archivos de código fuente de su proyecto, y vas a estar en el negocio.

    Origen está en SortableBindingList.zip

    • Esta solución no necesita LINQ y trabaja en .net 2.0 y hay otras funcionalidades que se encuentran en BindingList como la notificación de cambio. Gracias por compartir.
    • La fuente no existe, existe de todos modos para actualizar esto?
  3. 7

    su cuadrícula de datos debe estar enlazado a una lista que se puede ordenar en el primer lugar.

    Crear este controlador de eventos:

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

    E inicializar el caso de cada uno de sus datragrids como este:

            dataGridView1.DataBindingComplete += MakeColumnsSortable_DataBindingComplete;
    • Me gustó la idea de utilizar el DataBindingComplete evento, pero no la dirección de no tener un conjunto de datos que se pueden ordenar. He editado para que sea un poco más reutilizable
  4. 5

    Puede utilizar DataGridViewColoumnHeaderMouseClick evento como este :

    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()
        }
    }
    • quiero utilizar esta idea, pero ¿cómo puedo controlar el encabezado de la columna clic? para ordenar datagridview orden por la que se específica el nombre de la columna? gracias
    • El DataGridViewCellMouseEventArgs objeto contiene el «ColumnIndex» de la propiedad.
  5. 5

    No es necesario crear un enlace de origen de datos. Si desea aplicar la clasificación de todas sus columnas, aquí es una solución más genérica de la mina;

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

    Asegúrese de suscribirse a su cuadrícula de datos para el caso de ColumnHeaderMouseClick. Cuando el usuario hace clic en la columna que se va a ordenar de forma descendente. Si el mismo encabezado de columna se hace clic de nuevo, la clasificación será aplicado de forma ascendente.

    • Solución agradable. Gracias.
  6. 4

    Una forma más de hacer esto es usando el Sistema».Linq.Dinámica» de la biblioteca. Usted puede obtener esta biblioteca de Nuget. No hay necesidad de cualquier implementaciones personalizadas o se puede ordenar la Lista 🙂

    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;
    }
    • Funciona como un encanto, no puedo creer que nadie había dado una respuesta positiva para esto todavía
    • Uso OrderByDescending para la else caso sería mejor.
  7. 3


    no es simplemente la solución cuando el uso de Entity Framework (versión 6 en este caso). No estoy seguro, pero parece ObservableCollectionExtensions.ToBindingList<T> método devuelve la implementación de ordenable lista de enlaces. No he encontrado el código fuente para confirmar esta suposición, pero el objeto de regresar de este método funciona con DataGridView muy bien sobre todo a la hora de ordenar las columnas haciendo clic en sus cabeceras.

    El código es muy simple y se basa sólo en .net y entity framework clases:

    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;
  8. 2

    KISS : Keep it simple, stupid

    Forma Un:
    Implementar un SortableBindingList clase cuando les gusta usar Enlace de datos y clasificación.

    Forma B:
    El uso de un Lista de<cadena> clasificación también funciona, pero no funciona con Enlace de datos.

  9. 1

    Si usted obtiene un mensaje de error como

    Una excepción no controlada del tipo ‘System.NullReferenceException’
    ocurrió en System.Windows.Forms.dll

    si usted trabaja con SortableBindingList, el código probablemente utiliza algunos bucles sobre las filas de DataGridView y tratar de acceder a la última fila vacía! (BindingSource = null)

    Si no es necesario para permitir al usuario añadir nuevas filas directamente en el DataGridView esta línea de código fácilmente resolver el problema:

    InitializeComponent();
    m_dataGridView.AllowUserToAddRows = false; //after components initialized
    ...
  10. 1
    1. Crear una clase que contiene todas las propiedades que usted necesita, y rellenarlas en el 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. Crear un IComparer < Estudiante > de la clase, para ser capaz de clasificar a

      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. Dentro del formulario que contiene el control datagrid agregar

      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. Dentro de datagridview_ColumnHeaderMouseClick controlador de eventos hacer algo como esto

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

    Espero que esto ayude

  11. 0

    Sólo en caso de que alguien todavía lo busca, lo hice en VS 2008 C#.

    En el Caso de ColumnHeaderMouseClick, agregar un enlace de datos para el gridview, y enviar el pedido por el campo como un parámetro. Usted puede conseguir el clic de campo de la siguiente manera:

    dgView.Columns[e.ColumnIndex].Name

    En mi caso el de la cabecera de los nombres son similares a la vista de los nombres de campo.

  12. 0

    Tengo un BindingList<> objeto se unen como un origen de datos para dataGridView.

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

    Cuando hice clic en el encabezado de la columna, no la clasificación se lleva a cabo.
    He utilizado el SortableBindingList respuesta proporcionada por Tom Bushell.
    Haber incluido dos archivos de origen en mi proyecto

    1. SortableBindingList.cs
    2. PropertyComparer.cs

    A continuación, este cambio se realiza para mi código:

    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;

    Después de estos cambios que he realizado una generación en mi programa. Ahora soy capaz de ordenar haciendo clic en los encabezados de columna. Sólo dos líneas de la necesidad de cambiar, que se destacan en el fragmento de código anterior por trailing comentarios.

  13. 0

    Me sugieren el uso de una tabla de datos.DefaultView como un origen de datos. A continuación, la línea de abajo.

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

    Después de que el control gridview de sí mismo se encargará de gestionar la ordenación(Ascendente o Descendente es compatible.)

  14. 0

    poner esta línea en su formulario de windows (en la carga o mejor en un método público como «binddata» ):

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

    Poner este código en un archivo llamado DataGridViewExtensions.cs (o similar)

    //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);
    }
    }
  15. 0

    En mi caso, el problema era que yo había puesto mi DataSource como un object, que es la razón por la que no te ordenan. Después del cambio de object a un DataTable funciona bien sin ningún tipo de código de complemento.

Dejar respuesta

Please enter your comment!
Please enter your name here