在List 上对Datagridview数据源进行排序,其中T是匿名的

一个相对简单的问题。 我有一个datagridview,它所做的就是显示统计信息。 没有编辑/添加/删除行。 datagridview绑定到List。 我想要实现的是让用户能够对列进行排序。

class Market { public int Location {get;set;} public float Value {get;set;} //... } class City { public String Name {get;set;} //... } List _markets; List _cities; //Lists are populated. dataGridView1.DataSource = _markets.Select(market => new { _cities[market.Location].Name, market.Value}).ToList(); 

正如所料,列不可排序,但显示的信息是您想要的。 我的问题是如何根据具有最少复杂和最少代码量的列类型进行DataGridView排序,因为代码将在整个过程中多次使用。

此应用程序用于使用具有视图的数据库。 然后这些视图填充DataGridViews。 视图仍然存在,因此可能的解决方案可能是:

 DataBase.ViewMarketValue temp = new DataBase.ViewMarketValue() _markets.ForEach(market => temp.AddViewMarketValueRow(_cities[market.Location].Name, market.Value); dataGridView1.DataSource = temp; 

这导致了所需的:具有所有信息的数据网格视图,并且它是可排序的。 唯一的问题是在这方面使用视图似乎是错误的。 所以我该怎么做?

为了能够在DataGridView自动排序数据,您需要一个实现IBindingListView 。 在BCL中,实现此接口的唯一类是DataViewBindingSource (但后者仅支持基础数据源支持的排序)。

所以,你有几个选择:

  • 创建一个DataTable来保存数据,并将其绑定到DataGridView (它实际上将绑定到DataTableDefaultView
  • 创建自己的实现IBindingListView的集合类
  • 使用现有的实现,比如Marc Gravell在这篇文章中发布的AdvancedList类。 您还需要添加构造函数以根据查询结果构建列表:

     public AdvancedList(IEnumerable collection) { foreach (var item in collection) { Add(item); } } 

由于查询结果是匿名类型,因此无法直接调用构造函数。 解决该问题的最简单方法是通过创建将创建列表的通用方法来利用类型推断。 为方便起见,您可以将其创建为扩展方法:

 public static AdvancedList ToAdvancedList(this IEnumerable source) { return new AdvancedList(source); } 

然后你就可以这样使用它:

 dataGridView1.DataSource = _markets.Select(market => new { _cities[market.Location].Name, market.Value}).ToAdvancedList(); 

这就是我基于Thomas Levesque( https://stackoverflow.com/a/4702631/1720085 )和Mary Hamlin( https://stackoverflow.com/a/5805044/1720085 )的答案:

1)为我的静态类添加了一个名为Funcs的扩展方法

 static class Funcs { public static DataTable ToDataTable(this IList data) { PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T)); DataTable table = new DataTable(); foreach (PropertyDescriptor prop in properties) table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType); foreach (T item in data) { DataRow row = table.NewRow(); foreach (PropertyDescriptor prop in properties) row[prop.Name] = prop.GetValue(item) ?? DBNull.Value; table.Rows.Add(row); } return table; } } 

2)并使用它像:

 var query = _markets.Select(market => new { _cities[market.Location].Name, market.Value}).ToList(); dataGridView1.DataSource = Funcs.ToDataTable(query);