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

Nic*_*ock 7 c# linq sorting datagridview anonymous-types

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

class Market
{
    public int Location {get;set;}
    public float Value {get;set;}
    //...
}
class City
{
    public String Name {get;set;}
    //...
}

List<Market> _markets;
List<City> _cities;
//Lists are populated.

dataGridView1.DataSource = _markets.Select(market => 
    new { _cities[market.Location].Name, market.Value}).ToList();
Run Code Online (Sandbox Code Playgroud)

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

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

DataBase.ViewMarketValue temp = new DataBase.ViewMarketValue()

_markets.ForEach(market => temp.AddViewMarketValueRow(_cities[market.Location].Name, market.Value);
dataGridView1.DataSource = temp;
Run Code Online (Sandbox Code Playgroud)

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

Tho*_*que 11

为了能够自动对数据进行排序DataGridView,您需要一个实现的集合IBindingListView.在BCL中,实现此接口的唯一类是DataViewBindingSource(但如果底层数据源也支持它,后者仅支持排序).

所以,你有几个选择:

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

    public AdvancedList(IEnumerable<T> collection)
    {
        foreach (var item in collection)
        {
            Add(item);
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

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

public static AdvancedList<T> ToAdvancedList<T>(this IEnumerable<T> source)
{
    return new AdvancedList<T>(source);
}
Run Code Online (Sandbox Code Playgroud)

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

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