14

I am new with Linq and I would like to sort some data that are in the BindingList. Once I did my Linq query, I need to use back the BindingList collection to bind my data.

 var orderedList = //Here is linq query
 return (BindingList<MyObject>)orderedList;

This compiled but fails in execution, what is the trick?

David Hall
  • 32,624
  • 10
  • 90
  • 127
Patrick Desjardins
  • 136,852
  • 88
  • 292
  • 341

3 Answers3

20
new BindingList<MyObject>(orderedList.ToList())
leppie
  • 115,091
  • 17
  • 196
  • 297
5

You can't always cast any collection type into any other collection. In terms of when the the compiler checks casting, check out this post on Compile-time vs runtime casting

However, you can easily produce a BindingList from an enumerable by doing some of the plumbing yourself. Just add the following Extension Method onto any Enumerable type to convert the collection into a BindingList.

C#:

static class ExtensionMethods
{
    public static BindingList<T> ToBindingList<T>(this IEnumerable<T> range)
    {
        return new BindingList<T>(range.ToList());
    }
}

//use like this:
var newBindingList = (from i in new[]{1,2,3,4} select i).ToBindingList();

VB:

Module ExtensionMethods
    <Extension()> _
    Public Function ToBindingList(Of T)(ByVal range As IEnumerable(Of T)) As BindingList(Of T)
        Return New BindingList(Of T)(range.ToList())
    End Function
End Module

'use like this:
Dim newBindingList = (From i In {1, 2, 3, 4}).ToBindingList()
Community
  • 1
  • 1
KyleMit
  • 30,350
  • 66
  • 462
  • 664
  • When `T` implements `INotifyPropertyChanged`, you can about double your efficiency by iterating `range` and adding each item to the `BindingList` directly. As it is, `range.ToList()` will enumerate `range` to add each item to a `List` and then `BindingList` will enumerate that list (again) to hook up the `PropertyChanged` event handler to each item. Skipping `.ToList` could improve performance for a really large collection. – xr280xr Aug 22 '19 at 17:10
2

That above only works when your linq query's select projection is explicitly typed as MyObject rather than select new which creates an instance of an anonymous object. In such cases the typeof(orderedList.ToList()) winds up as something akin to this: System.Collections.Generic.List<<>f__AnonymousType1>

ie: this should work:

var result = (from x in MyObjects
              where (wherePredicate( x ))
              select new MyObject {
                  Prop1 = x.Prop1,
                  Prop2 = x.Prop2
              }).ToList();
return new BindingList<MyObject>( result );

this will not:

var result = from x in db.MyObjects
             where(Predicate(x))
             select new {
                Prop1 = x.Prop1
                Prop2 = x.Prop2
            };
return new BindingList<MyObject>(result.ToList())
//creates the error: CS0030 "Cannot convert type 'AnonymousType#1' to 'MyObject'

In the second case they typeof(result) is: System.Collections.Generic.List<<>f__AnonymousType2> (the type params match the properties set in your select projection)

reference: http://blogs.msdn.com/swiss_dpe_team/archive/2008/01/25/using-your-own-defined-type-in-a-linq-query-expression.aspx