Sort Datasridview datasource into List <T>, where T is anonymous
A relatively simple question. I have a datagridview, and all it does is display statistics. No edit / add / delete lines. Datagridview is tied to a list. All I want to achieve is for the user to sort the columns.
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(); As expected, the columns are not sorted, but the information that is displayed is what is required. My question is how to make the DataGridView sort based on the type of column with the least complex and least amount of code, since the code will be used multiple times.
This application used a database that has views. These views then populated DataGridViews. Views still exist, so a possible solution might be:
DataBase.ViewMarketValue temp = new DataBase.ViewMarketValue() _markets.ForEach(market => temp.AddViewMarketValueRow(_cities[market.Location].Name, market.Value); dataGridView1.DataSource = temp; The result is what you want: a datagridview that has all the information and is sorted. The only problem is that it seems wrong to use representations in this aspect. So what should I do?
To be able to sort data automatically in a DataGridView , you need a collection that implements IBindingListView . In BCL, the only classes that implement this interface are DataView and BindingSource (but the latter only supports sorting if the underlying data source supports it).
So you have a few options:
- create a
DataTableto store the data and bind it to theDataGridView(it will actually be bound to theDefaultViewDataTable) - create your own collection class that implements
IBindingListView use an existing implementation, such as the
AdvancedList<T>class posted by Mark Gravel in this post . You will also need to add a constructor to create a list from the result of your query:public AdvancedList(IEnumerable<T> collection) { foreach (var item in collection) { Add(item); } }
Since the result of your request is anonymous, you cannot directly call the constructor. The easiest way to get around this problem is to use type inference by creating a generic method that will create a list. For convenience, you can create it as an extension method:
public static AdvancedList<T> ToAdvancedList<T>(this IEnumerable<T> source) { return new AdvancedList<T>(source); } Then you can use it like this:
dataGridView1.DataSource = _markets.Select(market => new { _cities[market.Location].Name, market.Value}).ToAdvancedList();