views:

476

answers:

2

Hi,

From what I've learned, you can't cast to BindingList, but rather you can wrap your result from the Linq query with a NEW BindingList. However, this doesn't work for me, because my Original Binding list has some events attached to it and i would like to maintain the same events in my LINQ result set.

For example:

I have my main BindingList collection called "Reports" (of type IReport). This collection is being registered to an event as following: Reports.AddingNew += OnAddNewXReport;

now, when i would like to filter this big collection and extract only few matched items, i'm using Linq to get this matching list. To make this list a BindingList, i new to do the following:

var rs = Reports.Where(r => r.ReportType == ReportType.MyType).Select(o => (MyType) o);

return new BindingList<MyType>(rs.ToList());

As you can see, this newly created collection, will not fire when new item is being added.

Does anyone has any idea how to resolve this? is there anyway to close the event subscription from the original BindingList to the "filtered" BindingList?

Thanks for the help

+1  A: 

I think one of the simplest way to achieve this is something like this:

var rs = Reports.Where(r => r.ReportType == ReportType.MyType).Select(o => (MyType) o);

var bs = new BindingList<MyType>();
foreach(var r in rs)
  bs.Add(r);

Another way is to create descendant for BindingList and in constructor fires OnListChanged for every item in new list:

sealed class MyBindingList<T> : BindingList<T>
{
    public MyBindingList(IList<T> collection)
        : base(collection)
    {
        for(int i = 0; i < collection.Count; ++i)
        {
            OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, idx));
        }
    }
}
Sergey Teplyakov
I don't think he wanted ways to create a new `BindingList` from his elements (seeing as how he already does it with `new BindingList<MyType>(rs.ToList()); `) but rather a way so that events that are registered on `Reports` are transfered to the new `BindingList`
Dynami Le Savard
In my case the result would be the same, but GUI would contains all new values. Or I don't understand what means "transfered"?
Sergey Teplyakov
+2  A: 

I dont think there is an easy way to do this. I would make a derived BindingList<T> that chains and exposes the events you're interested in.

sealed class MyBindingList<T> : BindingList<T>
{
    public event EventHandler MyAddingNew;

    public MyBindingList(IList<T> collection)
        : base(collection)
    {
        //hook so that when BindingList.AddingNew is fired
        //it is chained to our new event
        base.AddingNew += MyBindingList_AddingNew;
    }

    public void MyBindingList_AddingNew(object sender, AddingNewEventArgs e)
    {
        if (MyAddingNew != null)
            MyAddingNew(sender, e);
    }

    public void RegisterEvents(MyBindingList<T> src)
    {
        //this is where you assign src events to your new list
        this.MyAddingNew = src.MyAddingNew;
    }
} 

Reason why you would need a derived type is that you cannot assign EventHandlers using just = (this.AddingNew = src.AddingNew) unless you're in the scope that defines it. When translated into your code you would have :

MyBindingList<MyType> Reports;
Reports.MyAddingNew += OnAddNewXReport;
var rs = Reports.Where(r => r.ReportType == ReportType.MyType)
                .Select(o => (MyType) o);    

MyBindingList<MyType> FilteredReports = new MyBindingList<MyType>(rs.ToList());
FilteredReports.RegisterEvents(Reports);
return FilteredReports;
Dynami Le Savard