C# DataGridView 使用通用列表作为底层源进行排序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1377568/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# DataGridView sorting with Generic List as underlying source
提问by PaN1C_Showt1Me
I'm using a Windows Forms DataGridViewto display a generic list of MyObject
objects.
我正在使用Windows 窗体 DataGridView来显示MyObject
对象的通用列表。
First of all I wrap this collection into a BindingSource
Collection, then:
首先我把这个集合包装成一个BindingSource
集合,然后:
dataGridView.DataSource = myBindingSource;
What I want to do is allow the user to sort the columns by clickin on the header of the column representing a concrete Property in MyObject.
我想要做的是允许用户通过单击代表 MyObject 中具体属性的列的标题来对列进行排序。
I've read some articles that I should do sorting before binding. But it does not help me if I want to sort the columns in real time, being said when it's already binded.
我读过一些我应该在绑定前进行排序的文章。但是如果我想实时对列进行排序,它对我没有帮助,在它已经绑定时说。
The question is, what exactly do I need to do, so I could see the sorting arrowsin DataGridView and I could sort every column?
问题是,我到底需要做什么,以便我可以在 DataGridView 中看到排序箭头,并且可以对每一列进行排序?
采纳答案by PaN1C_Showt1Me
My Solution is this:
我的解决方案是这样的:
I work with myBindingSource at my own, I do sorting, grouping ..whatever in a separate thread. Then I simply bind the result to the DataGridView.
我自己使用 myBindingSource,我在单独的线程中进行排序、分组 ..whatever 。然后我简单地将结果绑定到 DataGridView。
myDataGridView.DataSource = bindingSource;
For this purpose I've setted all the columns to be sorted 'Programatically'
(in designer)
Then I manually add the arrow (ASCENDING / DESCENDING)
by setting
为此,我设置了所有要排序的列'Programatically'
(在设计器中)然后我通过设置手动添加箭头(ASCENDING / DESCENDING)
cell.SortGlyphDirection = ... ;
in code behind.
在后面的代码中。
回答by IordanTanev
see this artice
看这篇文章
http://msdn.microsoft.com/en-us/library/0868ft3z.aspx
http://msdn.microsoft.com/en-us/library/0868ft3z.aspx
by reading it i saw this "This method sorts the contents of the DataGridView by comparing values in the specified column. By default, the sort operation will use the Compare method to compare pairs of cells in the column using the DataGridViewCell..::.Value property."
通过阅读它,我看到了“此方法通过比较指定列中的值对 DataGridView 的内容进行排序。默认情况下,排序操作将使用 Compare 方法使用 DataGridViewCell..:: 比较列中的单元格对。价值财产。”
Best Regards, iordan
最好的问候, 奥尔丹
回答by Asish
Complete code to sort the column of datagridview whose datasource is a generic List
数据源为泛型List的datagridview列排序的完整代码
//-----------------------------------------------------------------------------------------
//In the form - In constructor or form load, populate the grid.
//--------------------------------------------------------------------------------------------
List<student> students;
private void PopulateList()
{
student std1 = new student("sss", 15, "Female");
student std2 = new student("ddd", 12, "Male");
student std3 = new student("zzz", 16, "Male");
student std4 = new student("qqq", 14, "Female");
student std5 = new student("aaa", 11, "Male");
student std6 = new student("lll", 13, "Female");
students = new List<student>();
students.Add(std1);
students.Add(std2);
students.Add(std3);
students.Add(std4);
students.Add(std5);
students.Add(std6);
dataGridView1.DataSource = students;
}
//---------------------------------------------------------------------------------------------
//Comparer class to perform sorting based on column name and sort order
//---------------------------------------------------------------------------------------------
class StudentComparer : IComparer<Student>
{
string memberName = string.Empty; // specifies the member name to be sorted
SortOrder sortOrder = SortOrder.None; // Specifies the SortOrder.
/// <summary>
/// constructor to set the sort column and sort order.
/// </summary>
/// <param name="strMemberName"></param>
/// <param name="sortingOrder"></param>
public StudentComparer(string strMemberName, SortOrder sortingOrder)
{
memberName = strMemberName;
sortOrder = sortingOrder;
}
/// <summary>
/// Compares two Students based on member name and sort order
/// and return the result.
/// </summary>
/// <param name="Student1"></param>
/// <param name="Student2"></param>
/// <returns></returns>
public int Compare(Student Student1, Student Student2)
{
int returnValue = 1;
switch (memberName)
{
case "Name" :
if (sortOrder == SortOrder.Ascending)
{
returnValue = Student1.Name.CompareTo(Student2.Name);
}
else
{
returnValue = Student2.Name.CompareTo(Student1.Name);
}
break;
case "Sex":
if (sortOrder == SortOrder.Ascending)
{
returnValue = Student1.Sex.CompareTo(Student2.Sex);
}
else
{
returnValue = Student2.Sex.CompareTo(Student1.Sex);
}
break;
default:
if (sortOrder == SortOrder.Ascending)
{
returnValue = Student1.Name.CompareTo(Student2.Name);
}
else
{
returnValue = Student2.Name.CompareTo(Student1.StudentId);
}
break;
}
return returnValue;
}
}
//---------------------------------------------------------------------------------------------
// Performing sort on click on Column Header
//---------------------------------------------------------------------------------------------
private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
//get the current column details
string strColumnName = dataGridView1.Columns[e.ColumnIndex].Name;
SortOrder strSortOrder = getSortOrder(e.ColumnIndex);
students.Sort(new StudentComparer(strColumnName, strSortOrder));
dataGridView1.DataSource = null;
dataGridView1.DataSource = students;
customizeDataGridView();
dataGridView1.Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection = strSortOrder;
}
/// <summary>
/// Get the current sort order of the column and return it
/// set the new SortOrder to the columns.
/// </summary>
/// <param name="columnIndex"></param>
/// <returns>SortOrder of the current column</returns>
private SortOrder getSortOrder(int columnIndex)
{
if (dataGridView1.Columns[columnIndex].HeaderCell.SortGlyphDirection == SortOrder.None ||
dataGridView1.Columns[columnIndex].HeaderCell.SortGlyphDirection == SortOrder.Descending)
{
dataGridView1.Columns[columnIndex].HeaderCell.SortGlyphDirection = SortOrder.Ascending;
return SortOrder.Ascending;
}
else
{
dataGridView1.Columns[columnIndex].HeaderCell.SortGlyphDirection = SortOrder.Descending;
return SortOrder.Descending;
}
}
回答by The Dag
I find it hard to believe the grid doesn't provide basic sorting out of the box, no code needed. After all, it is pretty silly to have to handle a header click event and call DataGridView.Sort indicating the column (determined by what was clicked, tracked by the grid) and the sort direction (determined by current sort state, tracked by the grid).
我发现很难相信网格不提供开箱即用的基本排序,不需要代码。毕竟,必须处理标题单击事件并调用 DataGridView.Sort 指示列(由单击的内容确定,由网格跟踪)和排序方向(由当前排序状态确定,由网格跟踪)是非常愚蠢的)。
Why isn't there simply a SortMode or an AllowUserToSort property that does exactly the same thing by default?
为什么没有简单的 SortMode 或 AllowUserToSort 属性在默认情况下做完全相同的事情?
I've bound my grid to a List and the properties I've mapped columns to are all basic types like string, int, DateTime and so on. All of which are IComparable. So why on earth should I need to write even one line of code? Especially considering that the documentation reads:
我已将我的网格绑定到一个列表,并且我将列映射到的属性都是基本类型,如字符串、整数、日期时间等。所有这些都是 IComparable。那么到底为什么我需要写一行代码呢?特别是考虑到文档内容如下:
By default, users can sort the data in a DataGridView control by clicking the header of a text box column.
默认情况下,用户可以通过单击文本框列的标题对 DataGridView 控件中的数据进行排序。
That's the Framework 3.0 doc, and I'm targeting 3.5, but "other versions" all refer to versions of Visual Studio, not versions of the Framework. What on earth is going on here Microsoft?!?
那是 Framework 3.0 文档,我的目标是 3.5,但“其他版本”都是指 Visual Studio 的版本,而不是 Framework 的版本。微软这到底是怎么回事?!?
回答by Juan Camilo Caro
A good Solution in this article "Presenting the SortableBindingList": http://www.timvw.be/2007/02/22/presenting-the-sortablebindinglistt/
这篇文章“Presenting the SortableBindingList”中的一个很好的解决方案:http://www.timvw.be/2007/02/22/presenting-the-sortablebindinglistt/
回答by alex
You may also want to take a look to this post where you can get two interesting links to implement a customized SortableBindingList:
您可能还想看看这篇文章,在那里您可以获得两个有趣的链接来实现自定义的 SortableBindingList:
Sort Datagridview columns when datasource binded to List(Of T)
回答by Jeff Qi
Here is a simpler solution to sort by column using Reflection and Linq. dataGridView1's DataSource is set to compareList which is declared as:
这是使用反射和 Linq 按列排序的更简单的解决方案。dataGridView1 的 DataSource 设置为 compareList,声明为:
private List<CompareInfo> compareList;
private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
string strColumnName = dataGridView1.Columns[e.ColumnIndex].Name;
SortOrder strSortOrder = getSortOrder(e.ColumnIndex);
if (strSortOrder == SortOrder.Ascending)
{
compareList = compareList.OrderBy(x => typeof(CompareInfo).GetProperty(strColumnName).GetValue(x, null)).ToList();
}
else
{
compareList = compareList.OrderByDescending(x => typeof(CompareInfo).GetProperty(strColumnName).GetValue(x, null)).ToList();
}
dataGridView1.DataSource = compareList;
dataGridView1.Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection = strSortOrder;
}
private SortOrder getSortOrder(int columnIndex)
{
if (dataGridView1.Columns[columnIndex].HeaderCell.SortGlyphDirection == SortOrder.None ||
dataGridView1.Columns[columnIndex].HeaderCell.SortGlyphDirection == SortOrder.Descending)
{
dataGridView1.Columns[columnIndex].HeaderCell.SortGlyphDirection = SortOrder.Ascending;
return SortOrder.Ascending;
}
else
{
dataGridView1.Columns[columnIndex].HeaderCell.SortGlyphDirection = SortOrder.Descending;
return SortOrder.Descending;
}
}
public class CompareInfo
{
public string FileName { get; set; }
public string UAT_Folder { get; set; }
public string UAT_Path
{
get { return UAT_Folder + FileName; }
}
public string PROD_Folder { get; set; }
public string PROD_Path
{
get { return PROD_Folder + FileName; }
}
}
回答by Naren
Another option to solve the sorting issue with DataGridView when binding to List is, if you are not dealing with huge data set then probably you can attempt to convert the List to DataTable, and then bind the resulting DataTable to the BindingSource/DataGridView.
在绑定到 List 时解决 DataGridView 排序问题的另一个选择是,如果您不处理庞大的数据集,那么您可能可以尝试将 List 转换为 DataTable,然后将生成的 DataTable 绑定到 BindingSource/DataGridView。
This would the need for a custom implementation of IComparer. In my case, I was dealing with a smaller list but there were more fields to display. So implementing IComparer meant writing too much boiler plate code.
这将需要 IComparer 的自定义实现。就我而言,我正在处理一个较小的列表,但有更多的字段要显示。所以实现 IComparer 意味着编写太多的样板代码。
Check this for terse way of converting the List to DataTable: https://stackoverflow.com/a/34062898/4534493
检查这个将列表转换为数据表的简洁方法:https: //stackoverflow.com/a/34062898/4534493
回答by Andre Vallestero
If creating your own user control is preferable, you can make a custom sort method using the code below:
如果更可取的是创建自己的用户控件,则可以使用以下代码创建自定义排序方法:
private string _lastSortColumn;
private ListSortDirection _lastSortDirection;
public void Sort(DataGridViewColumn column)
{
// Flip sort direction, if the column chosen was the same as last time
if (column.Name == _lastSortColumn)
_lastSortDirection = 1 - _lastSortDirection;
// Otherwise, reset the sort direction to its default, ascending
else
{
_lastSortColumn = column.Name;
_lastSortDirection = ListSortDirection.Ascending;
}
// Prep data for sorting
var data = (IEnumerable<dynamic>)DataSource;
var orderProperty = column.DataPropertyName;
// Sort data
if (_lastSortDirection == ListSortDirection.Ascending)
DataSource = data.OrderBy(x => x.GetType().GetProperty(orderProperty).GetValue(x, null)).ToList();
else
DataSource = data.OrderByDescending(x => x.GetType().GetProperty(orderProperty).GetValue(x, null)).ToList();
// Set direction of the glyph
Columns[column.Index].HeaderCell.SortGlyphDirection
= _lastSortDirection == ListSortDirection.Ascending
? SortOrder.Ascending : SortOrder.Descending;
}
You can then override the header click method to call your sort function:
然后,您可以覆盖标题单击方法以调用排序函数:
protected override void OnColumnHeaderMouseClick(DataGridViewCellMouseEventArgs e)
{
base.OnColumnHeaderMouseClick(e);
var column = Columns[e.ColumnIndex];
if (column.SortMode == DataGridViewColumnSortMode.Automatic
|| column.SortMode == DataGridViewColumnSortMode.NotSortable)
Sort(column);
}