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

前端 未结 15 935
误落风尘
误落风尘 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:48

    your data grid needs to be bound to a sortable list in the first place.

    Create this event handler:

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

    And initialize the event of each of your datragrids like this:

            dataGridView1.DataBindingComplete += MakeColumnsSortable_DataBindingComplete;
    
    0 讨论(0)
  • 2020-12-02 15:48

    If you get an error message like

    An unhandled exception of type 'System.NullReferenceException' occurred in System.Windows.Forms.dll

    if you work with SortableBindingList, your code probably uses some loops over DataGridView rows and also try to access the empty last row! (BindingSource = null)

    If you don't need to allow the user to add new rows directly in the DataGridView this line of code easily solve the issue:

    InitializeComponent();
    m_dataGridView.AllowUserToAddRows = false; // after components initialized
    ...
    
    0 讨论(0)
  • 2020-12-02 15:49

    As Niraj suggested, use a SortableBindingList. I've used this very successfully with the DataGridView.

    Here's a link to the updated code I used - Presenting the SortableBindingList - Take Two

    Just add the two source files to your project, and you'll be in business.

    Source is in SortableBindingList.zip

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

    put this line in your windows form (on load or better in a public method like "binddata" ):

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

    Put this code in a file called DataGridViewExtensions.cs (or 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);
        }
    }
    
    0 讨论(0)
  • 2020-12-02 15:49

    In my case, the problem was that I had set my DataSource as an object, which is why it didn't get sorted. After changing from object to a DataTable it workd well without any code complement.

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

    You can use DataGridViewColoumnHeaderMouseClick event like this :

    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()
        }
    }
    
    0 讨论(0)
提交回复
热议问题