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

时间:2011-01-15 20:40:32

标签: 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();

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

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

DataBase.ViewMarketValue temp = new DataBase.ViewMarketValue()

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

这会产生所需的:datagridview,它包含所有信息并且可以排序。唯一的问题是在这方面使用视图似乎是错误的。那我该怎么办?

2 个答案:

答案 0 :(得分:11)

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

所以,你有几个选择:

  • 创建一个DataTable来保存数据,并将其绑定到DataGridView(它实际上会绑定到DefaultView的{​​{1}}
  • 创建自己的实现DataTable
  • 的集合类
  • 使用现有的实现,例如Marc Gravell在this post中发布的IBindingListView类。您还需要添加构造函数以根据查询结果构建列表:

    AdvancedList<T>

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

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

然后你可以这样使用它:

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

答案 1 :(得分:0)

这是我根据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<T>(this IList<T> 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);