C# 当用户单击列标题时,如何启用DataGridView排序?
我的表单上有一个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 })
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; ... }
}
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;
}
}
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答案。
在我的项目中包含了两个源文件
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);
}
}