Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/reporting-services/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当用户单击列标题时,如何启用DataGridView排序?_C#_Winforms_Sorting_Datagridview - Fatal编程技术网

C# 当用户单击列标题时,如何启用DataGridView排序?

C# 当用户单击列标题时,如何启用DataGridView排序?,c#,winforms,sorting,datagridview,C#,Winforms,Sorting,Datagridview,我的表单上有一个datagridview,我用以下内容填充它: dataGridView1.DataSource = students.Select(s => new { ID = s.StudentId, RUDE = s.RUDE, Nombre = s.Name, Apellidos = s.LastNameFather + " " + s.LastNameMother, Nacido = s.DateOfBirth })

我的表单上有一个datagridview,我用以下内容填充它:

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();
现在,我使用s.Apellidos作为默认排序,但我也希望允许用户在单击列标题时进行排序

这种排序将不会以任何方式修改数据,它只是客户端的一个额外功能,允许用户在用眼睛扫描屏幕时更轻松地搜索信息

感谢您的建议。

将所有列的(可由用户排序)SortMode属性设置为自动

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;
    }
编辑:由于datagridview与linq查询绑定,因此不会对其进行排序。因此,请浏览这个
[404死链接,请参阅下一节]
,它解释了如何创建可排序绑定列表,然后将其作为数据源提供给datagridview

从死链接恢复的代码 上面的链接是404死机。我从网页的互联网回送机中恢复了代码

public Form1()
{
    InitializeComponent();

    SortableBindingList<person> persons = new SortableBindingList<person>();
    persons.Add(new Person(1, "timvw", new DateTime(1980, 04, 30)));
    persons.Add(new Person(2, "John Doe", DateTime.Now));

    this.dataGridView1.AutoGenerateColumns = false;
    this.ColumnId.DataPropertyName = "Id";
    this.ColumnName.DataPropertyName = "Name";
    this.ColumnBirthday.DataPropertyName = "Birthday";
    this.dataGridView1.DataSource = persons;
}
public Form1()
{
初始化组件();
SortableBindingList persons=新建SortableBindingList();
新增(新增人员(1,“timvw”,新增日期时间(1980年4月30日));
添加(新的Person(2,“johndoe”,DateTime.Now));
this.dataGridView1.AutoGenerateColumns=false;
this.ColumnId.DataPropertyName=“Id”;
this.ColumnName.DataPropertyName=“Name”;
this.ColumnBirthday.DataPropertyName=“生日”;
this.dataGridView1.DataSource=个人;
}
  • 创建一个包含所有所需属性的类,并将它们填充到构造函数中

    class Student
    {
        int _StudentId;
        public int StudentId {get;}
        string _Name;
        public string Name {get;}
        ...
    
        public Student(int studentId, string name ...)
        { _StudentId = studentId; _Name = name; ... }
    }
    
  • 创建一个IComparer类,以便能够排序

    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;
        }
    }
    
  • 在datagridview_ColumnHeaderMouseClick事件处理程序中,执行以下操作

    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();
    }
    
    private void dgv_ColumnHeaderMouseClick(对象发送者,DataGridViewCellMouseeEventArgs e)
    {
    StudentSorter-sorter=null;
    string column=dGV.Columns[e.ColumnIndex].DataPropertyName;//如果设置了列名,请使用列名
    如果(列==“学生ID”)
    {
    分类器=新的学生分类器(StudentSorter.SField.StudentId,SetOrderDirection(列));
    }
    else if(列==“名称”)
    {
    sorter=新的StudentSorter(StudentSorter.SField.Name,SetOrderDirection(列));
    }
    ...
    列表lstFD=datagridview.DataSource作为列表;
    lstFD.分拣机(分拣机);
    datagridview.DataSource=lstFD;
    datagridview.Refresh();
    }
    

  • 希望这有帮助

    正如Niraj建议的那样,使用可排序绑定列表。我已经在DataGridView中非常成功地使用了它

    BindingList x1;
    x1 = new BindingList<sourceObject>();
    BindingSource bsx1 = new BindingSource();
    bsx1.DataSource = x1;
    dataGridView1.DataSource = bsx1;
    
    下面是我使用的更新代码的链接--

    只要将这两个源文件添加到您的项目中,您就可以开始工作了


    源代码位于-
    404死链接中

    您可以使用DataGridViewColumnHeaderMouseClick事件,如下所示:

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

    首先需要将数据网格绑定到可排序列表。

    创建此事件处理程序:

        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;
        }
    
    并初始化每个DatraGrid的事件,如下所示:

            dataGridView1.DataBindingComplete += MakeColumnsSortable_DataBindingComplete;
    

    吻:保持简单,笨蛋

    方式A: 当喜欢使用数据绑定和排序时,实现自己的类

    方式B:
    如果收到如下错误消息,则使用列表进行排序也可以,但不适用于数据绑定

    “System.NullReferenceException”类型的未处理异常 发生在System.Windows.Forms.dll中

    如果您使用SortableBindingList,您的代码可能会在DataGridView行上使用一些循环,并尝试访问空的最后一行!(BindingSource=null)

    如果您不需要允许用户直接在DataGridView中添加新行,这行代码可以轻松解决此问题:

    InitializeComponent();
    m_dataGridView.AllowUserToAddRows = false; // after components initialized
    ...
    

    为了防止有人还在找它,我在VS2008C#上做了

    在事件列HeaderMouseClick上,为gridview添加数据绑定,并像参数一样发送order by字段。您可以按如下方式获得单击的字段:

    dgView.Columns[e.ColumnIndex].Name
    
    在我的例子中,标题的名称类似于视图字段名称。

    我有一个BindingList对象绑定为dataGridView的数据源

    BindingList x1;
    x1 = new BindingList<sourceObject>();
    BindingSource bsx1 = new BindingSource();
    bsx1.DataSource = x1;
    dataGridView1.DataSource = bsx1;
    
    bindingslist-x1;
    x1=新绑定列表();
    BindingSource bsx1=新的BindingSource();
    bsx1.DataSource=x1;
    dataGridView1.DataSource=bsx1;
    
    当我单击列标题时,没有进行排序。 我使用了Tom Bushell提供的SortableBindingList答案。 在我的项目中包含了两个源文件

  • SortableBindingList.cs
  • 房地产比较公司
  • 然后对我的代码进行以下更改:

    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;
    
    Be.Timvw.Framework.ComponentModel.SortableBindingList x1;//1.
    x1=新的Be.Timvw.Framework.ComponentModel.SortableBindingList();//2.
    BindingSource bsx1=新的BindingSource();
    bsx1.DataSource=x1;
    dataGridView1.DataSource=bsx1;
    
    在这些更改之后,我在我的程序上执行了一个构建。我现在可以通过单击列标题进行排序。只有两行需要更改,它们在上面的代码段中通过尾随注释高亮显示


    当使用实体框架(本例中为版本6)时,有一个非常简单的解决方案。我不确定,但它似乎是
    ObservableCollectionExtensions.ToBindingList
    方法返回sortable绑定列表的实现。我还没有找到证实这一假设的源代码,但是从这个方法返回的对象与
    DataGridView
    配合得非常好,特别是当通过单击其标题对列进行排序时

    代码非常简单,仅依赖.net和实体框架类:

    使用System.Data.Entity;
    IEnumerable items=MethodCreatingItems();
    var observableItems=新系统.Collections.ObjectModel.ObservableCollection(项目);
    System.ComponentModel.BindingList源=observableItems.ToBindingList();
    MyDataGridView.DataSource=源;
    
    另一种方法是使用“System.Linq.Dynamic”库。您可以从中获取此库。我不需要任何定制
    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;
    }
    
    foreach (DataGridViewColumn column in gridview.Columns)
        {
           column.SortMode = DataGridViewColumnSortMode.Automatic;
        }
    
    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();
    }
    
    //
    // bind the data and make the grid sortable 
    //
    this.datagridview1.MakeSortable( myenumerablecollection ); 
    
    // 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);
        }
    }